0

モデルの rspec モックを使用してコントローラーでテストを作成しようとしていますが、次の場合にのみ機能するようです

Type.any_instance.should_recieve(...)

それ以外の

instancename.should_receive(...)

私のコードは次のようになります。(通常は FactoryGirl を使用しますが、問題がないことを確認するためにこの例には参加していません)

it "calls blah on foo" do
  foo = Foo.new
  foo.save
  foo.should_receive(:blah) #this fails because it's called 0 times
  #Foo.any_instance.should_receive(:blah) #this would succeed
  post :create, {:foo => foo}
end

そして私のコントローラーで

def create
  foo = Foo.find_by_id(params[:foo])
  foo.blah
  #other stuff thats not related
end

Foo.find_by_id をモックして foo を返すことができることはわかっていますが、それはとにかく返す必要があるため、そうする必要はないと感じています。つまり、find_by_id の使用をやめるとテストが中断することになりますが、これは実際にはそうではありません。重要な詳細。

私が間違っていることは何か分かりますか?どこでも any_instance を言う必要がなく、find_by_id をモックする必要がなければ、私のテストはより良いものになると思います。

4

1 に答える 1

2

実際のコードで呼び出されているのと同じfoo オブジェクトではないため、コードは機能しません。blah

仕様コードで、インスタンスを作成して保存します。

foo = Foo.new
foo.save

これにより、レコードが をfoo指す db に保存されます。次に、オブジェクトに期待値を設定します。

foo.should_receive(:blah)

この期待は、仕様とアプリ コードが同じオブジェクトを指している場合にのみ機能します。お気づきのように、たとえばスタブfind_by_idして返すことで、これを実現できます。または、任意のインスタンスに期待値を設定することもできます。これについても注意してください。

ただし、その期待はそのままでは機能しません。実際のコードでは、別のオブジェクトを作成しますfoo:

foo = Foo.find_by_id(params[:foo])
foo.blah

params[:foo]がレコードの ID である場合foo、仕様コードとfooアプリ コードの両方が同じレコードを指しますが、それはそれらが同じオブジェクトであることを意味しません (そうではありません)。

また、私の理解が正しければ、次のように考えています。

post :create, {:foo => foo}

次のようにする必要があります。

post :create, {:foo => foo.id}

したがって、一言で言えば、メッセージの期待値が必要な場合は、スタブするかfind、任意のインスタンスに期待値を適用する必要があります。(動的ファインダーはとにかく を呼び出し、テストをより堅牢にするため、findではなくスタブを使用できるはずです。)find_by_idfind

それが役立つことを願っています。

于 2013-04-29T04:27:20.313 に答える