2013-08-21 22 views
18

Come posso eseguire lo stub di un metodo solo alla prima chiamata e nella seconda deve comportarsi come previsto?metodo di stub solo alla prima chiamata con Rspec

ho il seguente metodo:

def method 
    do_stuff 
rescue => MyException 
    sleep rand 
    retry 
end 

Voglio la prima chiamata di do_stuff per aumentare MyException, ma in seconda convocazione, si comporta normalmente. Ho bisogno di raggiungere questo per testare il mio blocco rescue senza ottenere un ciclo infinito.

C'è un modo per raggiungere questo obiettivo?

risposta

15

È possibile passare un blocco a uno stub che verrà richiamato quando viene chiamato lo stub. È quindi possibile eseguire la stub in là, oltre a fare tutto il necessario.

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 

Sembra funzionare bene qui.

$ rspec stub.rb -f doc 

Stub once 
    should only stub once 

Finished in 0.00058 seconds 
1 example, 0 failures 

In alternativa, si può solo tenere traccia del numero di chiamate e restituire risultati diversi per lo stub sulla base del conteggio delle chiamate:

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

Questo ha risolto un problema che ho incontrato con la funzione di sola lettura di ActiveRecord - I aveva un modello marcato in sola lettura ('def readonly; true; end') ma aveva bisogno di creare le istanze in un test e non voleva modificare il codice di test con il codice di produzione. La soluzione (in fabbrica factory_girl): 'after (: build) do | f | f.stub (: readonly?) {f.unstub (: readonly?); falso}; f.save !; FINE' –

Problemi correlati