RSpecの使用中にスタブやモックを削除する方法はありますか?
例:
RestClient.should_receive(:delete).with("http://www.example.com")
...
...
# this will remove the mocking of "should_receive" and
# restore the proper "delete" method on "RestClient".
RestClient.mocking_reset
(mocking_reset
は、必要な機能の架空の名前です)。
「スタブ」をリセットするが「should_receive」をリセットしない「unstub」メソッドがあることを知っています。
それで、「should_receive」のために「unstub」と同等のメソッドはありますか?
パナヨティス
現時点(rspec-mocks 2.10.1)では、unstub
に相当するメソッドはありませんが、should_receive
用のメソッドがあります。 rspec_reset
を使用してすべてのスタブとモックをリセットできます。また、ダーティーハックを記述して特定の期待値を削除することもできます(これはお勧めしません)。
以下は、オブジェクトのすべてのスタブと期待値を削除する例です。
describe "resetting stubs and expectations with rspec_reset" do
before do
@person = mock('person')
@person.should_receive(:poke)
end
it "should not fail when we reset all stubs and expectations" do
@person.rspec_reset
end
end
このメソッドはrspecソースコードで@private
と注釈されていることに注意してください。これは、絶対に必要以上に使用することは避け、警告なしにrspecの将来のバージョンで機能しなくなる可能性があることを意味します。ただし、rspec自体の仕様ではかなり広く使用されているため、すぐに廃止される可能性は低くなります。
Rspec-mocksコードをもう少し掘り下げた後は、もちろん非常に厄介なことをして、特定の期待を自分で引き裂くことができます。
# Works in rspec 2.10.1
describe "removing an expectation with an ugly hack" do
before do
@person = mock('person')
@person.should_receive(:poke)
end
it "should not fail after we hack rspec by violating every law of good programming, ever" do
@person.instance_variable_get(:@mock_proxy).instance_variable_get(:@method_double)[:poke].clear
end
end
これはrspecテストパッケージのカプセル化に違反しているので、これは本当に悪いことです。代わりに、特定の期待値を削除する説得力のある理由が本当にある場合、正しい方法は、unstub
に並列メソッドを追加するrspec-mocksの上流にパブリックメソッドを追加することですが、特定の期待値を削除します。それはおそらくここにあります(このファイルのstub
とunstub
の定義にも注意してください):
https://github.com/rspec/rspec-mocks/blob/master/lib/rspec/mocks/methods.rb
外出して、期待を取り除くための上記の提案のいずれかを使用する前に、仕様で本当にこれを行う必要があるのか、それともリファクタリングする必要があるのかを検討する必要があります。 should_receive
の使用はコードに関するアサーションであり、通常は1つのことだけをアサートする例(つまりit
ブロック)を作成する必要があります。グローバル設定で過度に実行しようとしない限り(例:rspec_reset
またはbefore:allブロック)、または例で試行している場合を除いて、before :each
のようなものが必要な理由について、私は非常に興味があります。やり過ぎる(つまり、1つの例で複数のアサーションを使用する)。
もちろん、これに対する1つの例外は、rspec-mocksのテストスイートにあります。ここで、rspec_reset
は、スタブとモックを適用する機能をテストするサンプル間の状態をリセットするために使用されます。そうしていなければ、オブジェクトのスタブとモックのグローバルリセットに依存しないようにテストを改善できる可能性があります。
これがお役に立てば幸いです。unstub
に同等のメソッドを追加する正当なケースがあると思われる場合は、メッセージの期待のために(つまり、should_receive
を使用した後)お知らせください。これが問題ないことだと確信している場合は、このメソッドを追加し、上流に追加することを提案することを検討します。多分それはunset_expectation
と呼ばれるでしょうか?上記のコードと内部構造のガイダンスを自由に使用して、rspec-mocksのプルリクエストを自分でまとめてください。unstub
に相当するモックを作成するために受け入れられるかどうか確認します。
次の方法で、以前のモックの一部を上書きできます。
expect(RestClient).to receive(:delete).and_call_original
または、それがどのような期待でもなかった場合は、単純なスタブのみを使用します。
allow(RestClient).to receive(:delete).and_call_original
expect_any_instance_of
とallow_any_instance_of
も存在することに注意してください。
RSpec> = 2.14の場合、受け入れられた回答は機能しなくなります。このスレッドでベルンハルトケーラーの回答を参照します(リンクの腐敗を防ぐために以下に再現): rspecバージョン2.14の未定義のメソッド `rspec_reset '
ResetメソッドはRSpec 2.14には存在しません。代わりに、rspec-mocksプロジェクトのspec_helper.rbファイル内で定義されたヘルパーメソッドです。
module VerifyAndResetHelpers def verify(object) RSpec::Mocks.proxy_for(object).verify end def reset(object) RSpec::Mocks.proxy_for(object).reset end end
このメソッドは、問題のオブジェクトのクラス定義にリセットアクションを追加するのではなく、基になるプロキシにリセットアクションを委任していることがわかります。