2013-03-06 103 views
36

在rspec文檔中指出,我應該使用double方法來創建測試雙。 但是我可以看到,即使我不使用double,它也能正常工作。沒有使用double有什麼問題嗎?另外,如果我不使用雙如何MyClass得到stub和其他rspec方法?它們在rspec中運行時是否可用於所有對象?rspec中的double方法是什麼?

require 'spec_helper' 

class MyClass 

    def self.run 
     new.execute 
    end 

    def execute 
     'foo' 
    end 

end 

describe MyClass do 

    it 'should stub instance method' do 
     obj = MyClass.new 
     obj.stub(:execute).and_return('bar') 
     obj.execute.should == 'bar' 
    end 

    it 'should stub class method' do 
     MyClass.stub(:run).and_return('baz') 
     MyClass.run.should == 'baz' 
    end 

end 

回答

40

編輯:我剛剛重讀你的問題,並意識到我沒有完全回答它。留下我原來的答案,因爲它是相關的,但這裏是你的具體答案:

你不需要雙重的原因是因爲你是存根類方法,而不是實例方法。 double僅用於處理類的實例,而不是類本身。

解釋一倍多一些

老答案:

你應該總是當你可以用它代替試驗雙打真正的類。這將更多地運用你的代碼並使你的測試更全面。測試雙打用於你不能或不應該使用真實物體的情況。例如,如果一個類不能在沒有外部資源(如網絡或數據庫)的情況下實例化,或者具有大量的依賴關係,而只是測試使用它的某些東西,則可能需要創建一個雙重和存根一些方法在雙。

這裏有一個更具體的例子:假設您正在測試MyClass,但爲了實例MyClass,你需要在FooLogger經過:

mylogger = FooLogger.new 
myclass = MyClass.new logger: mylogger 

如果FooLogger.new打開系統日誌插座,並開始發送垃圾郵件的權利每當你運行測試時,你都會記錄下來。如果你不希望這個測試過程中,以垃圾郵件的日誌,可以代替一個雙重的FooLogger和存根出它的方法:

mylogger = double(FooLogger) 
mylogger.stub(:log) 
myclass = MyClass.new logger: mylogger 

因爲大多數設計良好的類可以無任何副作用被實例化效果,你通常可以使用真實的對象而不是雙重的,而stub方法。還有其他一些場景,其中類有很多依賴關係,使它們難以實例化,而雙打是一種通過徹底檢查並測試你真正關心的事情的方式。

根據我的經驗,需要使用double是代碼氣味,但我們經常需要使用不易更改的類(例如,從寶石中),所以它是您不時需要的工具。

+0

其實當你在看我的例子,第一個規範存根**實例方法**,第二個存根**類方法**。它看起來像兩個工作正常,沒有使用'雙'之前使用。這就是爲什麼我想知道什麼是一個額外的'雙'給我的魔法。 – grafthez 2013-03-06 17:45:00

+0

看看我創建的https://gist.github.com/anonymous/5101448這個例子。如果我想測試'SchedulerJob',我需要存根'RequestSchedule'並模擬'RequestToQueuePusher'嗎?另外困擾我的是'SchedulerJob'與兩個剩餘的類緊密結合。當我來自Java世界時,我通常會將它們作爲依賴項提取,因爲沒有簡單的方法來僞造以硬編碼方式創建的對象。在Ruby中,它似乎不是一個問題。我看到很多像「SchedulerJob」這樣的對象。我知道有一種方法可以很容易地僞裝它們,但對我來說,這違反了一些固體原理 – grafthez 2013-03-06 18:06:15

+0

這也是Ruby世界中糟糕的設計。應該有一種方法來注入RequestSchedule依賴關係,以便於測試。你可以這樣做:'fakeschedule = double(RequestSchedule); RequestSchedule.stub(新).and_return(fakeschedule);'。它當然應該重構。 – 2013-03-06 18:42:00

0

隨着RSpec Mocks 3.0雙打的行爲已經改變。您現在可能需要verify doubles,這意味着「RSpec將檢查方法 被底層對象實際上是否存在於底層對象上」,但「如果未定義底層對象或類,則不會進行檢查」。

驗證雙精度請求您具體瞭解double類型(實例,類,對象,動態類,部分)。下面是來自RSpec Relish一個實例雙例子:

RSpec.describe User, '#suspend!' do 
    it 'notifies the console' do 
    notifier = instance_double("ConsoleNotifier") 

    expect(notifier).to receive(:notify).with("suspended as") 

    user = User.new(notifier) 
    user.suspend! 
    end 
end 
相關問題