あるクラスのインスタンスをスタブしようとしています。メソッドをスタブする必要がありfetch
ます。これにより、自己にデータが入力されます。
変数にアクセスして変更し、メソッドself
に戻るにはどうすればよいですか?fetch
MyObject.any_instance.stub(:fetch) { self }
MyObject
インスタンスを返しません。
おそらく、この状況ではモックの方が便利です。残念ながら、私はまだそれらを理解していません。
これに対処するための未解決の 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.new
fetch
とはいえ、「テストに耳を傾ける」ことが重要であり、テストが困難な場合は、すぐにany_instance
. あなたの元の質問は、私があなたのデザインについて何かを推測するのに十分なコンテキストを提供しませんが、これを行う必要がある場合は間違いなくここから始めます.
私が見る限り、これは何らかの理由で可能ではないようです。現在の実装を確認しましたが、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の専門家ではありません。