2014-06-25 25 views
22

Ich habe ein Modul, das in einem anderen Modul enthalten ist, und beide implementieren die gleiche Methode. Ich möchte das Verfahren des eingeschlossenen Modul Stummel, etwa wie folgt:Gibt es eine Möglichkeit, eine Methode eines enthaltenen Moduls mit Rspec zu stubben?

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 

Der erste Test ist vorbei, aber die zweiten Ausgänge:

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

    expected: :bar 
     got: :M 

Warum ist nicht der Stub Arbeits in diesem Fall? Gibt es einen anderen Weg, dies zu erreichen?

Danke!

------------------------------------- UPDATE -------- --------------------------

Danke! using allow_any_instance_of (M) löste diesen. Meine nächste Frage ist - was passiert, wenn ich prepend verwende und nicht einbeziehe? siehe den folgenden Code:

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 

Dieses Mal unter Verwendung von allow_any_instance_of (M) resultiert in einer unendlichen Schleife. Warum das?

Antwort

23

Hinweis Sie können nicht direkt M.foo anrufen! Ihr Code scheint nur zu funktionieren, weil Sie M.foo verspottet haben, um :bar zurückzugeben.

Wenn Sie A metaclass öffnen (class << self) M aufzunehmen, müssen Sie eine Instanz von M verspotten, dass auf Ihre before Block erweitert:

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

Dies funktioniert. Im Gegensatz zu "allow" benötigt "allow_any_instance_of" offenbar nicht, dass die Methode für das Objekt definiert wird. –

+1

Ich denke, das hat mir gerade dabei geholfen, 5+ Stunden zu lösen, um meinen Kopf auf den Tisch zu schlagen. Vielen Dank! – Derek

+2

Vgl. 'Expect_any_instance_of' ... das brachte mich auf den richtigen Weg –