Istnieją dwa problemy, na które musimy się tutaj zwrócić.
Po pierwsze, wydaje się, że patrzysz na wszystkie swoje testy z perspektywy testu jednostkowego. Testy jednostkowe są niezwykle cenne, ale nie są jedynymi rodzajami testów. Testy można w rzeczywistości podzielić na kilka różnych warstw, od bardzo szybkich testów jednostkowych przez mniej szybkie testy integracyjne do jeszcze wolniejszych testów akceptacyjnych . (Można wyłamać jeszcze więcej warstw, np . Testy funkcjonalne ).
Po drugie, łączysz wywołania kodu zewnętrznego z logiką biznesową, co stwarza wyzwania testowe i może sprawić, że Twój kod będzie bardziej kruchy.
Testy jednostkowe powinny być szybkie i powinny być przeprowadzane często. Wyśmiewanie zależności pomaga w szybkim działaniu tych testów, ale może potencjalnie wprowadzić dziury w zasięgu, jeśli zależność się zmieni, a próbka się nie zmieni. Kod może zostać uszkodzony, gdy testy będą nadal działać na zielono. Niektóre kpiące biblioteki ostrzegają o zmianie interfejsu zależności, inne nie.
Z drugiej strony testy integracyjne służą do testowania interakcji między komponentami, w tym bibliotekami stron trzecich. Na tym poziomie testowania nie należy używać prób, ponieważ chcemy zobaczyć, jak rzeczywisty obiekt współdziała ze sobą. Ponieważ używamy prawdziwych obiektów, testy te będą wolniejsze i nie będziemy uruchamiać ich tak często, jak nasze testy jednostkowe.
Testy akceptacyjne wyglądają na jeszcze wyższym poziomie, sprawdzając, czy wymagania dotyczące oprogramowania są spełnione. Testy te działają na całym, kompletnym systemie, który zostałby wdrożony. Po raz kolejny nie należy używać kpiny.
Jedną z wytycznych, które ludzie uznali za wartościową w odniesieniu do prób, jest nie kpić z typów, których nie posiadasz . Amazon jest właścicielem interfejsu API do S3, dzięki czemu mogą się upewnić, że pod nimi się nie zmieni. Ty natomiast nie masz tych zapewnień. Dlatego jeśli wyśmiejesz interfejs S3 API w testach, może on zmienić i zepsuć kod, podczas gdy wszystkie testy będą miały kolor zielony. Jak więc przeprowadzamy test jednostkowy kodu, który korzysta z bibliotek stron trzecich?
Cóż, my nie. Postępując zgodnie z wytycznymi, nie możemy kpić z obiektów, których nie jesteśmy właścicielami. Ale… jeśli posiadamy nasze bezpośrednie zależności, możemy wyśmiewać je. Ale jak? Tworzymy własne opakowanie dla interfejsu API S3. Możemy sprawić, że będzie wyglądać podobnie do S3 API, lub możemy dostosować go do naszych potrzeb (preferowane). Możemy nawet uczynić to trochę bardziej abstrakcyjnym, powiedz PersistenceService
raczej niż an AmazonS3Bucket
. PersistenceService
byłby interfejs z metodami takimi jak #save(Thing)
i #fetch(ThingId)
, rodzajami metod, które chcielibyśmy zobaczyć (są to przykłady, możesz chcieć różnych metod). Możemy teraz zaimplementować PersistenceService
interfejs API S3 (powiedzmy a S3PersistenceService
), odsuwając go od naszego kodu wywołującego.
Teraz kod, który wywołuje interfejs API S3. Musimy zastąpić te wywołania wywołaniami do PersistenceService
obiektu. Używamy zastrzyku zależności, aby przekazać nasz PersistenceService
obiekt. Ważne jest, aby nie prosić o S3PersistenceService
, ale prosić o PersistenceService
. To pozwala nam zamienić implementację podczas naszych testów.
Cały kod, który używał bezpośrednio interfejsu API S3, teraz używa naszego PersistenceService
, a S3PersistenceService
teraz wykonuje wszystkie wywołania interfejsu API S3. W naszych testach możemy wykpić się PersistenceService
, ponieważ jesteśmy jego właścicielem, i użyć makiety, aby upewnić się, że nasz kod wykonuje prawidłowe wywołania. Ale teraz to pozostawia sposób testowania S3PersistenceService
. Ma taki sam problem jak poprzednio: nie możemy przetestować urządzenia bez wezwania zewnętrznego serwisu. Więc… nie testujemy tego jednostkowo. My mogli naśmiewać się z zależnościami S3 API, ale to dałoby nam trochę do żadnej dodatkowej pewności siebie. Zamiast tego musimy przetestować to na wyższym poziomie: testy integracyjne.
Może to zabrzmieć trochę niepokojąco, mówiąc, że nie powinniśmy testować jednostkowo części naszego kodu, ale spójrzmy na to, co osiągnęliśmy. Wszędzie mieliśmy mnóstwo kodu, w którym nie mogliśmy przeprowadzić testu jednostkowego, który teraz można przetestować za pomocą PersistenceService
. Mamy bałagan w bibliotece stron trzecich ograniczony do jednej klasy implementacji. Ta klasa powinna zapewniać niezbędną funkcjonalność do korzystania z interfejsu API, ale nie jest do niego dołączona żadna zewnętrzna logika biznesowa. Dlatego po napisaniu powinien być bardzo stabilny i nie powinien się bardzo zmieniać. Możemy polegać na wolniejszych testach, które nie uruchamiamy tak często, ponieważ kod jest stabilny.
Następnym krokiem jest napisanie testów integracji S3PersistenceService
. Powinny być one oddzielone według nazwy lub folderu, abyśmy mogli je uruchomić oddzielnie od naszych szybkich testów jednostkowych. Testy integracyjne mogą często wykorzystywać te same ramy testowe, co testy jednostkowe, jeśli kod jest wystarczająco informacyjny, więc nie musimy uczyć się nowego narzędzia. Rzeczywisty kod do testu integracji jest tym, co napiszesz dla Opcji 1.