2014-06-25 22 views
22

Mam moduł, który jest zawarty w innym module, i obie implementują tę samą metodę. Chciałbym skrótową metody modułu cenie, coś takiego:Czy istnieje sposób na pobranie metody z dołączonego modułu za pomocą 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 

Pierwszy test przechodzi, ale drugi wyjścia:

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

    expected: :bar 
     got: :M 

Dlaczego nie jest obróbka stub w tym przypadku? Czy jest inny sposób na osiągnięcie tego?

Dzięki!

------------------------------------- AKTUALIZACJA -------- --------------------------

Dzięki! użycie parametru allow_any_instance_of (M) rozwiązało ten problem. Moje następne pytanie brzmi: co się stanie, jeśli użyję funkcji przedrostka i nie uwzględnię? patrz poniższy kod:

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 

tym razem stosując allow_any_instance_of (M) powoduje w nieskończonej pętli. dlaczego?

Odpowiedz

23

Uwaga: nie można bezpośrednio zadzwonić pod numer M.foo! Twój kod wydaje się działać tylko dlatego, że wyśmiewałeś M.foo, aby zwrócić :bar.

Po otwarciu A metaklasa (class << self) obejmuje M, trzeba kpić każdą instancję M, że jest dodanie do bloku before:

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

To działa. Wygląda na to, że w przeciwieństwie do 'allow',' allow_any_instance_of' nie wymaga zdefiniowania metody na obiekcie. –

+1

Myślę, że to właśnie pomogło mi rozwiązać 5+ godzin, waląc głową w stół. dzięki! – Derek

+2

Cf., 'expect_any_instance_of' ... to postawiło mnie na właściwej drodze –