LoginSignup
4
4

More than 3 years have passed since last update.

rspecで「あるメソッドが呼ばれたこと/呼ばれていないこと」をテストするやり方

Last updated at Posted at 2019-08-17

環境

  • Rails 5.2.3
  • rspec 3.8.2

やり方 その一

beforeallow(...).to receive(...)して、
itexpect(...).to have_received(...)する。

context 'when ...' do
  before do
    allow(Rails.logger).to receive(:error).with('error occurred')
  end

  it '...' do
    do_something
    expect(Rails.logger).to have_received(:error).with('error occurred').once
  end

  # 「呼ばれていないこと」を確認するためには、.to have_received を .not_to have_received にします。
  it '...' do
    do_something
    expect(Rails.logger).not_to have_received(:error).with('error occurred')
  end

end

controllerのmethodをmockする場合は、allow(controller).to receive(:some_method).and_return(true)でOK。

やり方 その二

beforeexpect(...).to receive(...)するだけでも動きます(期待動作します)。
しかし、rubocop-rspecRSpec/ExpectInHook: Do not use expect in before hook(「beforeブロックでexpectを使用するな」)
と怒られます。

context 'when ...' do
  before do
    expect(Rails.logger).to receive(:error).with('some message').once
  end
end

なので it の中で定義したほうが良さそうです。

context 'when ...' do
  it do
    expect(Rails.logger).to receive(:error).with('some message').once
    do_something
  end
end

しかし、↓のような感じで戻り値がある場合は、have_receivedが使えないので、このやり方(beforeに書くやり方)しかないように思うけど、何かいいやり方あるのかな?

  before do
    result = AuthenticateUser.call(token)
    expect(AuthenticateUser).to receive(:call).with(token).and_return(result)
  end

その他

以下のコードをモックする。

order = Order.by(customer).ordered_today.not_paid.order(created_at: :desc).first
if order&.purchased_but_not_paid?
  @order = order
end
before do
  order_class_double = class_double(Order)
  order_instance_double = instance_double(Order, id: 1)

  allow(Order).to receive(:by).and_return(order_class_double)
  allow(order_class_double).to receive(:ordered_today).and_return(order_class_double)
  allow(order_class_double).to receive(:not_paid).and_return(order_class_double)
  allow(order_class_double).to receive(:order).and_return(order_class_double)
  allow(order_class_double).to receive(:first).and_return(order_instance_double)
  allow(order_instance_double).to receive(:purchased_but_not_paid?).and_return(true)
end
4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4