2014-06-25 20 views
22

Ho un modulo incluso in un altro modulo e entrambi implementano lo stesso metodo. Vorrei stub il metodo del modulo incluso, qualcosa di simile a questo:C'è un modo per stubare un metodo di un modulo incluso con Rspec?

module M 
    def foo 
    :M 
    end 
end 

module A 
    class << self 
    include M 

    def foo 
     super 
    end 
    end 
end 

describe "trying to stub the included method" do 
    before { allow(M).to receive(:foo).and_return(:bar) } 

    it "should be stubbed when calling M" do 
    expect(M.foo).to eq :bar 
    end 

    it "should be stubbed when calling A" do 
    expect(A.foo).to eq :bar 
    end 
end 

Il primo test sta passando, ma la seconda uscite:

Failure/Error: expect(A.foo).to eq :bar 

    expected: :bar 
     got: :M 

Perché non è la lavorazione stub in questo caso? C'è un modo diverso per raggiungere questo obiettivo?

Grazie!

------------------------------------- AGGIORNAMENTO -------- --------------------------

Grazie! usando allow_any_instance_of (M) risolto questo. La mia prossima domanda è: cosa succede se uso anteporre e non includere? vedere il codice seguente:

module M 
    def foo 
    super 
    end 
end 

module A 
    class << self 
    prepend M 

    def foo 
     :A 
    end 
    end 
end 

describe "trying to stub the included method" do 
    before { allow_any_instance_of(M).to receive(:foo).and_return(:bar) } 

    it "should be stubbed when calling A" do 
    expect(A.foo).to eq :bar 
    end 
end 

Questa volta, utilizzando allow_any_instance_of (M) risultato in un ciclo infinito. perché?

risposta

23

Nota: non è possibile chiamare direttamente M.foo! Il tuo codice sembra funzionare solo perché hai preso in giro M.foo per restituire :bar.

Quando si apre A metaclasse (class << self) per includere M, è necessario prendere in giro qualsiasi istanza di M, che è l'aggiunta al vostro before blocco:

allow_any_instance_of(M).to receive(:foo).and_return(:bar)

module M 
    def foo 
    :M 
    end 
end 

module A 
    class << self 
    include M 

    def foo 
     super 
    end 
    end 
end 

describe "trying to stub the included method" do 
    before do 
    allow(M).to receive(:foo).and_return(:bar) 
    allow_any_instance_of(M).to receive(:foo).and_return(:bar) 
    end 


    it "should be stubbed when calling M" do 
    expect(M.foo).to eq :bar 
    end 

    it "should be stubbed when calling A" do 
    expect(A.foo).to eq :bar 
    end 
end 
+0

Questo funziona. Apparentemente, a differenza di 'allow',' allow_any_instance_of' non richiede che il metodo sia definito sull'oggetto. –

+1

Penso che questo mi abbia aiutato a risolvere almeno 5 ore di battere la testa sul tavolo. Grazie! – Derek

+2

Cf., 'expect_any_instance_of' ... questo mi ha messo sulla strada giusta –