17

あるクラスのインスタンスをスタブしようとしています。メソッドをスタブする必要がありfetchます。これにより、自己にデータが入力されます。

変数にアクセスして変更し、メソッドselfに戻るにはどうすればよいですか?fetch

MyObject.any_instance.stub(:fetch) { self }

MyObjectインスタンスを返しません。

おそらく、この状況ではモックの方が便利です。残念ながら、私はまだそれらを理解していません。

4

2 に答える 2

16

これに対処するための未解決の rspec-mocks issueがあります。いつかそれに対処したいと思っていますが、ブロック実装で使用する既存の仕様スイートを壊さない方法でこれを追加するのは簡単ではありませんany_instance.追加の引数(例えば、オブジェクトインスタンス)。

全体として、any_instance状況によっては便利ですが、少し匂いがします。個々のインスタンスをモックまたはスタブする方法を見つけることができれば、一般的に問題は少なくなります。

これは私がテストしていないがうまくいくはずの回避策です:

orig_new = MyObject.method(:new)
MyObject.stub(:new) do |*args, &block|
  orig_new.call(*args, &block).tap do |instance|
    instance.stub(:fetch) { instance }
  end
end

基本的に、インスタンス化された新しいインスタンスごとにスタブできるようにany_instance、フックしてここでシミュレートしています。MyObject.newfetch

とはいえ、「テストに耳を傾ける」ことが重要であり、テストが困難な場合は、すぐにany_instance. あなたの元の質問は、私があなたのデザインについて何かを推測するのに十分なコンテキストを提供しませんが、これを行う必要がある場合は間違いなくここから始めます.

于 2012-12-15T19:40:00.517 に答える
2

私が見る限り、これは何らかの理由で可能ではないようです。現在の実装を確認しましたが、rspec-mocks実際にスタブ実装を呼び出す方法は次のようです。

# lib/rspec/mocks/message_expectation.rb:450
def call_implementation(*args, &block)
    @implementation.arity == 0 ? @implementation.call(&block) : @implementation.call(*args, &block)
end

どうやら、ブロックは、を介してではなく、単にそれ自体で呼び出されますinstance_eval。たぶん、あなたが望むことを達成するための別のテクニックがありますが、結局のところ、私は決してRSpecの専門家ではありません。

于 2012-12-15T18:06:57.540 に答える