2010-01-29 9 views
11

Ich bin auf dieses Problem mit Tests gestoßen. Nehmen wir an, ich habe zwei Modelle, User und Post, wo user has_many: posts hat.Mocking ActiveRecord Beziehungsverhalten in RSpec-Tests

Ich versuche, einen Code-Block, der so etwas wie beinhaltet bis spec:

user = User.find(123) 
post = user.posts.find(456) 

Ich weiß, wie die User.find und user.posts Teile verspotten. Der user.posts Mock gibt ein Array von Post-Objekten zurück. Und wenn es zum .find(456) Teil kommt, bricht alles mit Ausnahme no block given zusammen.

Also meine Frage hier ist: Was gebe ich als Ergebnis der user.posts Mock, so dass .find(456) Methode funktioniert es? User.first.posts.class sagt, es ist Array, aber offensichtlich gibt es etwas mehr, dass die AR-Stil finden Anrufe funktionieren. Ich bin nicht überglücklich von der Aussicht, die Find-Methode für das zurückgegebene Objekt zu verspotten.

PS Bevor Sie vorschlagen, die offensichtliche und gute Antwort von aufhören zu verspotten und mit Fixtures/Seeding die Test-Datenbank mit den notwendigen Daten, hier ist das Catch: Legacy-Schema. Sowohl Benutzer als auch Post arbeiten oben auf Datenbankansichten, nicht auf Tabellen, und sie zu ändern, so dass sie Tabellen in der Testdatenbank sind, scheint mir falsch zu sein.

Antwort

16

Das Problem ist, dass user.posts ist nicht tatsächlich eine einfache Array; Es ist ein Assoziations-Proxy-Objekt. Die Art und Weise, es zu Stummel ist wahrscheinlich so etwas wie (obwohl die genaue Syntax, auf dem Mockframework ab, die Sie verwenden):

def setup 
    @user = mock(User) 
    User.stub(:find).with(123).return(@user) 
    user_posts = mock(Object) 
    @user.stub(:posts).return(user_posts) 
    @post = mock(Post) 
    user_posts.stub(:find).with(456).return(@post) 
end 

Dann in Ihrem Test, User.find(123)@user zurückkehren und @user.posts.find(456) werden @post zurück. Wenn Sie @user.posts benötigen, um mehr von den Array in Ihren Tests zu handeln, können Sie eine mock(Array) erstellen und die [](index) Methode stub.

+1

, dass die ‚hässliche‘ Art und Weise, die ich nicht tun wollte, aber Ihre Erwähnung Verband Proxy-Objekt 'gibt mir die Schlüsselwörter, die ich vermisste, und die Suche danach führten zu dem, wonach ich gesucht hatte, danke! –

+7

@Toms, Wenn Ihre Lösung unter diesen Antworten eindeutig ist, könnten Sie vielleicht hinzufügen hinzufügen als eine andere Antwort. Ich würde gerne sehen, wie du es gelöst hast. –

+0

Der hässliche Weg, verspottet Mocks. Ich war einfach glücklich, das herauszufinden - war nicht das erste Mal, dass ich diese Situation antraf, und es stört mich. –

7
+1

für rspec 3.2 [receive_message_chain] (https://relishapp.com/rspec/rspec-mocks/v/3-2/docs/working-with-legacy-code/message-chains) – ryan2johnson9