2016-05-16 56 views
2

的實例變量我有兩個類OneClassAnotherClass我如何可以模擬在rspec的

class OneClass 
    def initialize(*args) 
    @another_member = AnotherClass.new() 
    end 

    def my_method() 
    if @another_member.another_method1() then 
     @another_member.another_method2() 
    end 
    @another_member.another_method3() 
    end 
end 

我正在寫單位OneClass。 我該如何模擬@another_member

回答

0

隨着安東尼的想法,我讓它工作。

describe OneClass do 
    before(:each) { @one_object = OneClass.new } 

    describe 'my_method' do 
    it 'should work' do 
     mock_member = double 
     allow(mock_member).to receive(:another_method1).and_return(true) 
     @one_object.instance_variable_set(:@another_member, mock_member) 

     @one_object.my_method() 

     expect(mock_member).to have_received(:another_method1) 
    end 
    end 
end 
0

可以間接磕碰AnotherClass.new嘲笑@another_member

another_member_double = double() 
allow(AnotherClass).to receive(:new).and_return(another_member_double) 

expect(another_member_double).to receive(:another_method1).and_return(somevalue) 
2

你不能嘲笑一個實例變量。你只能嘲笑方法。一種選擇是在OneClass內部定義一個包裝another_member的方法,並嘲笑該方法。

class OneClass 
    def initialize(*args) 
    end 

    def my_method() 
    if another_member.another_method1() then 
     another_member.another_method2() 
    end 
    another_member.another_method3() 
    end 

    private 

    def another_member 
    @another_member ||= AnotherClass.new() 
    end 

end 

但是,您不必,有更好的方法來編寫和測試您的代碼。在這種情況下,更好的嘲笑方法是使用名爲Dependency Injection的模式。

將您的依賴關係傳遞給初始值設定項。 (注意我使用了關鍵字參數,但是你不必這樣做,你也可以使用標準args方法)。

然後,在測試套件中,您只需提供測試對象。

let(:test_another) { 
    Class.new do 
    def another_method1 
     :foo 
    end 
    def another_method2 
     :bar 
    end 
    def another_method3 
     :baz 
    end 
    end 
} 

it "does something" do 
    subject = OneClass.new(another: test_another) 
    # ... 
end 

這種方法有幾個優點。特別是,您避免在測試中使用模擬,並且確實在單獨測試對象。