2013-08-21 2 views
18

最初の呼び出しでメソッドをスタブする方法と、2番目の呼び出しでメソッドを期待どおりに動作させる方法はありますか?スタブメソッドRspecを使用した最初の呼び出しでのみ

私は、次の方法があります。

def method 
    do_stuff 
rescue => MyException 
    sleep rand 
    retry 
end 

を私はMyExceptionを上げるdo_stuffの最初の呼び出しにしたいが、2回目の呼び出しでは、正常に動作します。無限ループを起こさずにブロックrescueをテストするには、これを達成する必要があります。

これを達成する方法はありますか?

答えて

15

ブロックを、スタブが呼び出されたときに呼び出されるスタブに渡すことができます。必要に応じて、アンスタブを実行することができます。

class Foo 
    def initialize 
    @calls = 0 
    end 

    def be_persistent 
    begin 
     increment 
    rescue 
     retry 
    end 
    end 

    def increment 
    @calls += 1 
    end 
end 

describe "Stub once" do 
    let(:f) { Foo.new } 
    before { 
    f.stub(:increment) { f.unstub(:increment); raise "boom" } 
    } 

    it "should only stub once" do 
    f.be_persistent.should == 1 
    end 
end 

ここでうまく動作するようです。

$ rspec stub.rb -f doc 

Stub once 
    should only stub once 

Finished in 0.00058 seconds 
1 example, 0 failures 

代わりに、あなただけの呼び出しの数を追跡し、呼び出し回数に基づいてスタブのために異なる結果を返すことができます:

describe "Stub once" do 
    let(:f) { Foo.new } 

    it "should return different things when re-called" do 
    call_count = 0 
    f.should_receive(:increment).twice { 
     if (call_count += 1) == 1 
     raise "boom" 
     else 
     "success!" 
     end 
    } 

    f.be_persistent.should == "success!" 
    end 
end 
+0

これは私がのActiveRecordの読み取り専用機能でに走った問題を解決した - I readonly( 'def readonly; true; end')とマークされたモデルを持っていましたが、テストでインスタンスを作成する必要があり、テストコードを実動コードでmuxしたくありませんでした。 (factory_girlファクトリ内の)解決策: 'after(:build)do | f | f.stub(:readonly?){f.unstub(:readonly?); false}; f.save!終わり –