2013-05-29 10 views
6

Ho un oggetto MyObject:Come si esegue lo stub di un metodo di un'istanza solo se una variabile di istanza specifica ha un valore?

class MyObject 

    def initialize(options = {}) 
    @stat_to_load = options[:stat_to_load] || 'test' 
    end 

    def results 
    [] 
    end 
end 

voglio stub metodo solo se stat_to_load = "times"results. Come lo posso fare? Ho provato:

MyObject.any_instance.stubs(:initialize).with({ 
    :stat_to_load => "times" 
}).stubs(:results).returns(["klala"]) 

ma non funziona. Qualche idea?

+1

Posso vedere una mancata corrispondenza su 'risultato' rispetto a' risultati' nella domanda. Probabilmente non è la tua risposta, ma vale la pena ripararla? –

+0

Oups, errore di copia/incolla – Sebastien

+0

Non so nemmeno se questo è possibile, ma probabilmente la soluzione corretta è iniettare l'oggetto o la classe, quindi si ha molto più controllo su di esso. Difficile dire/dare esempi senza vedere come si usa questo codice. –

risposta

0

Quindi, penso che ci sia probabilmente un modo più semplice per testare quello che stai cercando di testare, ma senza più contesto non so cosa consigliare. Tuttavia, qui è un codice proof-of-concept per dimostrare che ciò che si vuole fare si può fare:

describe "test" do 
    class TestClass 
    attr_accessor :opts 
    def initialize(opts={}) 
     @opts = opts 
    end 

    def bar 
     [] 
    end 
    end 
    let!(:stubbed) do 
    TestClass.new(args).tap{|obj| obj.stub(:bar).and_return("bar")} 
    end 
    let!(:unstubbed) { TestClass.new(args) } 

    before :each do 
    TestClass.stub(:new) do |args| 
     case args 
     when { :foo => "foo" } 
     stubbed 
     else 
     unstubbed 
     end 
    end 
    end 

    subject { TestClass.new(args) } 

    context "special arguments" do 
    let(:args) { { :foo => "foo" } } 
    its(:bar) { should eq "bar" } 
    its(:opts) { should eq({ :foo => "foo" }) } 
    end 

    context "no special arguments" do 
    let(:args) { { :baz => "baz" } } 
    its(:bar) { should eq [] } 
    its(:opts) { should eq({ :baz => "baz" }) } 
    end 

end 

test 
    special arguments 
    bar 
     should == bar 
    opts 
     should == {:foo=>"foo"} 
    no special arguments 
    bar 
     should == [] 
    opts 
     should == {:baz=>"baz"} 

Finished in 0.01117 seconds 
4 examples, 0 failures 

Comunque io sto facendo un sacco di utilizzo del soggetto speciale/lasciare blocchi di contesto qui. Vedi http://benscheirman.com/2011/05/dry-up-your-rspec-files-with-subject-let-blocks/ per ulteriori informazioni su questo argomento.

+0

Questa risposta è per RSpec non moka –

0

provare qui di seguito, questo dovrebbe funzionare come previsto:

Qui, sostanza in realtà stiamo spegnendo new instance sempre creato e anche spegnendo results metodo per l'istanza che sta ottenendo restituito.

options = {:stat_to_load => "times"} 
MyObject.stubs(:new).with(options) 
        .returns(MyObject.new(options).stubs(:results).return(["klala"])) 
0

È possibile utilizzare il vecchio vecchio Ruby all'interno del test per ottenere ciò.

MyObject.class_eval do 
    alias_method :original_results, :results 
    define_method(:results?) do 
    if stats_to_load == "times" 
     ["klala"] 
    else 
     original_results 
    end 
    end 
end