2013-05-20 14 views
1

如何將嘲笑或重寫Kernel.system方法正確的方法,這樣,當一個名爲:如何模擬或重寫Kernel.system?

system("some command") 

,而不執行命令的,其執行一些預定義的代碼?

我嘗試添加以下到我的測試類:

module Kernel 
    def system 
     puts "SYSTEM CALL!!" 
    end 
end 

但正如預期的,相反,執行測試時,系統調用運行它沒有工作。

回答

3

如果你談論的是單元測試和使用Rspec的,你應該能夠做到這一點是這樣的:

Kernel.should_receive(:system) 

或稍微鬆:

Kernel.stub(:system) 

更多信息:https://www.relishapp.com/rspec/rspec-mocks/v/2-13/docs/message-expectations/expect-a-message

+0

你能不能給我一個的RSpec良好的文檔鏈接? –

+1

我給你的鏈接來自官方rspec文檔:https://www.relishapp.com/rspec/。 您也可以查看http://betterspecs.org/ - 它提供了一些關於如何正確使用rspec的最佳實踐。 – Spajus

+0

謝謝!先生:)它看起來不錯。 –

4

由於這個問題被問到,RSpec 3已經出來了一個新的語法,你會寫這個:

expect(Kernel).to receive(:system) 

如果你的代碼檢查系統調用是否是成功的,您可以指定結果是這樣的:

expect(Kernel).to receive(:system).and_return(true) 

的寬鬆版:

allow(Kernel).to receive(:system).and_return(true) 
+2

僅供參考使用紅寶石2.3。0和rspec-core 3.4.2,我不得不使用'Kernel.system(...)'而不是'system(...)'來讓模擬通過。 – Dennis

2

在某些情況下,這樣做expect(Kernel).to receive(:system)是不足夠的。

考慮這個例子:

foo_component.rb

class FooComponent 
    def run 
    system('....') 
    end 
end 

foo_component_spec.rb

require 'spec_helper' 

describe FooComponent do 
    let(:foo_component) { described_class.new } 

    describe '#run' do 
    it 'does some awesome things' do 
     expect(Kernel).to receive(:system).with('....') 
     foo_component.run 
    end 
    end 
end 

它不會工作。這是因爲Kernel是一個模塊,Object(父類)在Kernel模塊中混合,使得所有Kernel方法在「全局」範圍內可用。

這就是正確的測試應該是這樣的:

require 'spec_helper' 

describe FooComponent do 
    let(:foo_component) { described_class.new } 

    describe '#run' do 
    it 'does some awesome things' do 
     expect(foo_component).to receive(:system).with('....') 
     foo_component.run 
    end 
    end 
end