2012-06-01 74 views
32

使用RSpec時,有任何方法可以刪除任何殘留和嘲諷嗎?在RSpec中,是否有一種方法等價於「unstub」,但是是「should_receive」?

例子:

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」的任何方法?

Panayotis

+0

很荒謬的是,你不能編輯少於6個字符!你的方法名稱上面寫着'mocking_resest',它應該說'mocking_reset'。 –

+0

添加一條編輯消息,您的編輯將超過6個字符:) – Galen

回答

29

在時刻(RSpec的-嘲笑2.10.1)沒有一個方法等同於unstubshould_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的,嘲笑的代碼挖多一點之後,你當然可以做一些令人頭痛和撕裂出一個具體的期望自己:

# 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添加了一個並行方法,但是用於刪除特定期望。它很可能是位於此處(注意stubunstub的定義,以及在該文件中):

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

外出前和使用任何的上述建議去除期望你可能要考慮,如果你的規格真的需要這樣做,或者如果他們應該重構。使用should_receive是關於你的代碼的斷言,通常你應該嘗試創建只聲明一件事的例子(即it塊)。我會很好奇你爲什麼需要像rspec_reset這樣的東西,除非你想在全局設置中做太多事情(例如,before :each或之前的所有塊),或者如果你的例子試圖做太多(即與多個斷言在一個例子中)。

一個例外情況當然可以在rspec-mocks測試套件中,其中rspec_reset用於在測試應用樁和模擬功能的示例之間重置狀態。除非你這樣做,否則你的測試可能會得到改進,從而不依賴對象上的存根和嘲諷的全局重置。

我希望這可以幫助,請讓我知道,如果你認爲有一個合法的情況下添加一個等效的方法unstub但消息的期望(即使用should_receive後)。如果我確信這是一件好事,我會考慮添加這種方法,並建議將其添加到上游。也許它會被稱爲unset_expectation?也請隨意使用上面的代碼和內部結構的指導來自行制定rspec-mocks的pull請求,我們將看看它是否被接受來創建一個等效於unstub的嘲諷。

+1

非常感謝您的答案。我想要這個功能的原因是因爲我有一個「clean_test_data」方法執行「之後:每個」。這需要使用真實的方法。在SOF上發佈我的問題後,我意識到我仍然可以使用「clean_test_data」,但是在「之前:每個」之前,這就是解決我的問題的方法。這樣,我終於不需要任何未知的或unmock。 同時,由於我發現以前有很好的理由使用「unstub」,所以我不明白爲什麼沒有完全相同的「unset_expectation」,然後讓模擬用戶決定。 –

6

對於RSpec> = 2.14,接受的答案將不再起作用。我是指你伯恩哈德·科勒的答案在此線程(轉載如下,以防止死鏈接):undefined method `rspec_reset' with rspec version 2.14

復位方法不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 

你可以看到,這個方法委託復位動作到 底層的代理,而不是在套結它的 有問題的對象的類定義。

31

您可以覆蓋一些以前的嘲弄:

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

,或者如果它不是任何一種期待,只是一個簡單的存根:

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

記住還存在expect_any_instance_ofallow_any_instance_of

相關問題