47

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」メソッドがあることを私は知っています。

それで、「unstub」に相当するが「should_receive」のための方法はありますか?

パナヨティス

4

3 に答える 3

54

次の方法で、以前のモックを上書きできます。

expect(RestClient).to receive(:delete).and_call_original

または、それが何の期待もしていない場合は、単純なスタブです。

allow(RestClient).to receive(:delete).and_call_original

expect_any_instance_ofとも存在することを思い出してくださいallow_any_instance_of

于 2015-01-27T09:04:54.583 に答える
32

現時点(rspec-mocks 2.10.1)ではunstubbut for に相当するメソッドはありません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 コードをもう少し掘り下げた後、もちろん、本当に厄介なことをして、1 つの特定の期待を自分で引き裂くことができます。

# 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 テスト パッケージのカプセル化に違反しているため、非常に悪いことであり、実行すべきではありません。代わりに、特定の期待を削除するやむを得ない理由がある場合は、rspec-mocks のアップストリームにパブリック メソッドを追加して、unstub特定の期待を削除するための並列メソッドを追加するのが正しい方法です。おそらくここにあります(このファイルのstubとの定義に注意してください):unstub

https://github.com/rspec/rspec-mocks/blob/master/lib/rspec/mocks/methods.rb

外に出て期待を取り除くために上記の提案のいずれかを使用する前に、仕様が本当にこれを行う必要があるかどうか、またはそれらをリファクタリングする必要があるかどうかを検討することをお勧めします。Usingshould_receiveはコードに関するアサーションであり、通常はit1 つのことだけをアサーションするサンプル (つまりブロック) を作成するようにしてください。rspec_resetグローバルセットアップでやりすぎない限り(たとえばbefore :each、または :all ブロッ​​クの前に)、または例がやりすぎないように(つまり、複数のアサーションを使用して)、次のようなものが必要な理由について非常に興味があります単一の例で)。

これに対する 1 つの例外は、もちろん、rspec_resetスタブとモックを適用する機能をテストするサンプル間で状態をリセットするために使用される rspec-mocks のテスト スイートである可能性があります。そうしない限り、オブジェクトのスタブとモックのグローバル リセットに依存しないようにテストを改善できる可能性があります。

これがお役に立てば幸いです。また、同等のメソッドを追加する正当なケースがあると思われる場合はお知らせくださいunstubが、メッセージの期待のため (つまり、使用後should_receive) です。これが問題ないと確信できる場合は、このメソッドを追加し、上流に追加することを提案することを検討します。多分それは呼ばれるunset_expectationでしょうか?また、上記のコードと内部構造のガイダンスを自由に使用して、自分で rspec-mocks のプル リクエストをまとめてくださいunstub

于 2012-06-02T17:02:50.770 に答える