2010-01-29 12 views
11

Zaskoczyłem ten problem podczas testowania. Załóżmy, że mam dwa modele, User i Post, gdzie użytkownik has_many: posty.Wyśmiewanie powiązania ActiveRecord w testach RSpec

Próbuję spec się blok kodu, który zawiera coś takiego:

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

wiem jak wyśmiewać się z User.find i user.posts części. Mock user.posts zwraca tablicę obiektów Post. A gdy dojdzie do części .find(456), wszystko zepsuje się z wyjątkiem no block given.

Moje pytanie brzmi: co mam zwrócić w wyniku próbkowania user.posts, dzięki czemu działa na nim metoda .find(456)? User.first.posts.class mówi, że to Array, ale oczywiście jest coś, co sprawia, że ​​wywołania AR-style działają. Nie jestem zachwycony perspektywą wyszydzania metody znalezienia na zwróconym obiekcie.

PS Zanim zasugerujesz oczywistą i dobrą odpowiedź na temat przestoju, wyśmiewania się i używania urządzeń/zasiewania testowej bazy danych z niezbędnymi danymi, oto haczyk: starszy schemat. Zarówno użytkownik, jak i post pracują nad widokami bazy danych, a nie tabelami, i zmieniając je tak, aby były tabelami w testowej bazie danych, wydają mi się błędne.

Odpowiedz

16

Problem polega na tym, że user.posts nie jest w rzeczywistości prosty Array; to obiekt stowarzyszenia proxy. Sposobem na to jest skrótową prawdopodobnie coś takiego (choć dokładna składnia zależy od szyderczy ramy używasz):

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 

Następnie w teście User.find(123) powróci @user i @user.posts.find(456) powróci @post. Jeśli potrzebujesz @user.posts, aby zachowywać się jak bardziej w testach Array, możesz utworzyć mock(Array) i odgadnąć metodę [](index).

+1

To jest „brzydki” sposób, że nie chciał zrobić, ale twoja wzmianka o „obiektu proxy stowarzyszenia” dostarczyła mi słów kluczowych, których mi brakowało, a poszukiwanie go doprowadziło do tego, czego szukałem, dzięki! –

+7

@Tomy, jeśli twoje rozwiązanie jest unikalne wśród tych odpowiedzi, może możesz dodać je jako inną odpowiedź. Chciałbym zobaczyć, jak to rozwiązałeś. –

+0

Brzydki sposób, drwi z mocks. Po prostu ucieszyłem się z tego - nie pierwszy raz spotkałem się z tą sytuacją i to mnie martwiło. –

7
+1

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

Powiązane problemy