RSpec:メソッドが呼び出されたかどうかをテストする方法は?


112

RSpecテストを書くとき、テストの実行中にメソッドが確実に呼び出されるようにするために、次のようなコードをたくさん書いていることに気づきました(引数として、状態を実際に問い合わせることはできないとしましょう)メソッドが実行する操作はその効果を確認するのが容易ではないため、呼び出し後のオブジェクトの)。

describe "#foo"
  it "should call 'bar' with appropriate arguments" do
    called_bar = false
    subject.stub(:bar).with("an argument I want") { called_bar = true }
    subject.foo
    expect(called_bar).to be_true
  end
end

私が知りたいのは、これより優れた構文はありますか?上記のコードを数行に減らすファンキーなRSpecの素晴らしさを逃していますか?should_receiveそれはこれを行うべきであるように聞こえますが、それをさらに読むと、それは正確にそれがすることではないように聞こえます。


3
ここで確認してください:stackoverflow.com/questions/1328277/...
kddeisz

@Peter Alfvin OPがで構文を要求していたshould_receiveので、その質問が役立つと思いました。
kddeisz 2014年

回答:


141
it "should call 'bar' with appropriate arguments" do
  expect(subject).to receive(:bar).with("an argument I want")
  subject.foo
end

1
この例では、「to .. receive(:bar)」のこの形式が「called_bar」の値をチェックする方法を理解できません。それを説明してもらえますか?
ecoding5

2
@ ecoding5いいえ。そうではなく、どちらもをチェックするべきではありませんcalled_bar。これは、メソッドが呼び出されたことを確認するためのフラグにすぎexpect(...).to receive(...)ませんが、すでにカバーしています。より明確でセマンティックです
wacko 2015年

@wacko oooh、わかりました。それをクリアしてくれてありがとう。初めては聞き取れませんでした。
ecoding5


37

以下はうまくいくはずです

describe "#foo"
  it "should call 'bar' with appropriate arguments" do
     subject.stub(:bar)
     subject.foo
     expect(subject).to have_received(:bar).with("Invalid number of arguments")
  end
end

ドキュメント:https : //github.com/rspec/rspec-mocks#expecting-arguments


ありがとう-「NoMethodError」を受け取っていたhas_received?-これはrspec versoinsと関係があるかもしれないと思います。私のために機能する別の解決策(上記で正しくマークされた解決策)を見つけました
Mikey Hogarth

@MikeyHogarthこの答えは、私が知っているRSpecのどのバージョンの一部でもhave_receivedないhas_received、ではなく(事実 "スパイ"アプローチの後に)示唆していたものです。
Peter Alfvin、2014年

2

RSpec〜> 3.1構文とrubocop-rspecルールのデフォルトオプションに完全に準拠するために、次RSpec/MessageSpiesのことを実行できますspy

メッセージの期待値は、テスト対象のコードを呼び出す前に、例の期待値を最初に置きます。多くの開発者は、テストの構造化に、arrange-act-assert(または指定されたとき)パターンを使用することを好みます。スパイは、テストパターンdoubleの代替タイプであり、have_receivedを使用して、事後にメッセージが受信されることを期待できるようにすることで、このパターンをサポートします。

# arrange.
invitation = spy('invitation')

# act.
invitation.deliver("foo@example.com")

# assert.
expect(invitation).to have_received(:deliver).with("foo@example.com")

rubocop-rspecを使用しない場合、またはデフォルト以外のオプションを使用する場合。もちろん、RSpec 3のデフォルトをexpectで使用することもできます。

dbl = double("Some Collaborator")
expect(dbl).to receive(:foo).with("foo@example.com")
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.