2016-05-16 5 views
2

でインスタンス変数を模擬することができます私は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

あなたはインスタンス変数を模擬することはできません。メソッドをモックすることしかできません。 1つの方法は、another_memberをラップし、そのメソッドをモックするメソッドOneClassを定義することです。

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というパターンを使用することです。

依存関係を初期化子に渡します。

class OneClass 
    def initialize(another: AnotherClass, whatever:, somethingelse:) 
    @another_member = another.new() 
    end 

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

(注:キーワード引数を使用しましたが、そうする必要はありません。標準の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 

このアプローチにはいくつかの利点があります。特に、テストでモックを使用することは避け、実際にはオブジェクトを単独でテストします。