1

RSpecメソッドが特定のブロックを受け取ることを確認するにはどうすればよいですか? 次の簡単な例を考えてみましょう。

class MyTest
  def self.apply_all_blocks(collection, target)
    collection.blocks.each do |block|
      target.use_block(&block)
    end
  end
end

target.use_blockによって返される各ブロックで が呼び出されることを検証する仕様が必要ですcollection.blocks

次のコードは機能しません。

describe "MyTest" do
  describe ".apply_all_blocks" do
    it "applies each block in the collection" do
      target = double(Object)
      target.stub(:use_block)

      collection = double(Object)
      collection.stub(:blocks).and_return([:a, :b, :c])

      target.should_receive(:use_block).with(:a)
      target.should_receive(:use_block).with(:b)
      target.should_receive(:use_block).with(:c)

      MyTest.apply_all_blocks(collection, target)
    end
  end
end

(また、use_block必ずしもブロックを呼び出すとは限らないため、ブロックが を受け取ることをテストするだけでは十分ではcallありません。同様に、私が望むことをするとは思いませんtarget.should_receive(:use_block).and_yield。)

4

2 に答える 2

3

シンボルの代わりにラムダを作成すると、期待どおりに機能します。

describe "MyTest" do
  describe ".apply_all_blocks" do
    let(:a) { lambda {} }
    let(:b) { lambda {} }
    let(:c) { lambda {} }
    it "applies each block in the collection" do
      target = double(Object)
      target.stub(:use_block)

      collection = double(Object)
      collection.stub(:blocks).and_return([a, b, c])

      target.should_receive(:use_block).with(&a)
      target.should_receive(:use_block).with(&b)
      target.should_receive(:use_block).with(&c)

      MyTest.apply_all_blocks(collection, target)
    end
  end
end

注:クラス名を から に変更しTestMyTestので、実際に実行されます。実際のクラスTestと衝突します。Testカットアンドペーストで実行できるように、質問も修正しました。

于 2013-05-28T14:26:34.557 に答える
1

これは古い質問であることは知っていますが、現在受け入れられている回答は正しくありません。

should_receive特定のブロックが受信されたことを確認する正しい方法は、受信したブロックと受信する予定のブロックを明確に比較する検証ブロックを渡すことです。

RSpec 2.13 (元の質問の時点で最新):

a = lambda {}
target.should_receive(:use_block) do |&block|
  expect(block).to eq(a)
end

RSpec 3.4 (これを書いている時点で最新):

a = lambda {}
expect(target).to receive(:use_block) do |&block|
  expect(block).to eq(a)
end

rspec はそのブロックを使用して戻り値を設定し、メソッドが実際に受信したブロックと比較しないため、別の回答で提案されているようにブロックを渡すwithことは、ブロックが実際に受信されたことを確認するのに十分ではありません。

のブロックの受け渡しに関するドキュメントを参照してくださいreceive

RSpec メーリング リストでの最近の議論も参照してください。

于 2016-02-19T16:30:29.960 に答える