Piszę testy Rspec dla obiektu usługi, który dotyka kilku modeli, ale mam wrażenie, że mój test jest zbyt zależny od elementów wewnętrznych metody i dlatego nie jest zbyt znaczący. Oto przykład:Porady Rspec dotyczące testowania obiektów usługowych
class MealServicer
def self.serve_meal(meal, customer)
meal.update_attributes(status: "served", customer_id: customer.id)
order = customer.order
OrderServicer.add_meal_to_order(meal, order)
CRM.update_customer_record(customer) // external API call
end
end
Chciałbym użyć podwójnych/odcinki drwić zachowanie faktycznie bez zapisywania czegokolwiek do testowej bazy danych (dla wydajności). Ale jeśli tworzę podwójne, które odpowiadają na wiadomości, to wydaje mi się, że testuję jedną konkretną implementację metody serve_meal(), a ten test jest zbyt sprzężony z tą konkretną implementacją. Na przykład, muszę się upewnić, że mój customer
double odpowiada na order
i zwraca kod order
. Zasadniczo, kiedy wszystko jest po prostu podwójne i muszę wyraźnie określić wszystkie zależności, upewniając się, że debile zwracają inne debla, wydaje się, że testy kończą się bezsensownie. Zobacz tutaj:
it "has a working serve_meal method" do
meal = double(:meal)
customer = double(:customer)
order = double(:order)
allow(customer).to_receive(:order).and_return(order)
allow(OrderServicer).to_receive(:add_meal_to_order).and_return(true)
allow(CRM).to_receive(:update_customer_record).and_return(true)
expect(meal).to receive(:update_attributes).once
expect(OrderServicer).to receive(:add_meal_to_order).once
expect(CRM).to receive(:update_customer_record).once
end
Czy jest jakiś inny sposób na sprawdzenie tego dokładnie i sensownie, inne niż rzeczywiste instancji posiłku, klientów oraz przedmiotów zamówień związanych odpowiednio (i ewentualnie zapisane w datbase), a następnie sprawdzić, czy MealServicer.serve_meal (...) aktualizuje właściwości obiektu zgodnie z oczekiwaniami? To ostatecznie spowoduje zapisanie do bazy danych, ponieważ update_attributes wykonuje wywołanie zapisu, a więc kilka metod, które zamierzam uwzględnić w metodzie obiektu usługi.
Wreszcie, ponieważ testy zależą od implementacji, nie mogę napisać testów przed metodą, co zalecają zwolennicy TDD. To po prostu czuje się do tyłu. Wszelkie porady dotyczące pisania wydajnych, ale użytecznych testów?
Tak jesteś w zasadzie stubbing najbardziej rzeczywistego kodu, więc nie będą tak naprawdę sprawa metoda zawiedzie, chyba że faktycznie z niego usuwać wierszy . Biorąc pod uwagę naturę obiektu, ten rodzaj logiki biznesowej jest czymś, co testowałem bardziej na poziomie integracji zamiast testu jednostkowego. Masz do czynienia z wieloma obiektami, które robią różne rzeczy. I naprawdę czytając twoją metodę, to brzmi jak cecha spec. Byłbym ciekawy, jak wykorzystujesz MealServicer w aplikacji. Ale nie martw się o używanie tych rzeczywistych obiektów.Napisz test na to, czego się spodziewasz po wywołaniu tej metody – agmcleod