2008-12-15 12 views
5

Pracuję nad projektem, w którym jest dużo zewnętrznych wiadomości usługowych. Dobrym sposobem na opisanie tego w nieco "hiperboli" byłoby aplikacja, w której system musi wysyłać wiadomości do interfejsu Flicker API, interfejsu API Facebooka i interfejsu API Netflix.Używanie próbnych obiektów poza testowaniem, zła praktyka?

Aby obsłużyć rozłączone scenariusze, problemy z logowaniem, użyteczność programistów, konfigurację itp. Eksperymentowałem z wykorzystaniem podejścia, które w dużym stopniu wykorzystuje drzewa generyczne i wyrażenia. Wynik końcowy wygląda tak:

Messenger<NetflixApi>.SendCustom(netflix => netflix.RecommendMovie("my message")); 

Ogólnie jestem zadowolony z efektu końcowego, ale czuję się jakbym popełnił błąd, albo wychodził na główny projekt gdzieś w odniesieniu do badań i odłączony scenariuszy.

Podczas testów, zautomatyzowanych, opartych na jednostkach lub ludziach, zaimplementowałem fabrykę obiektów, która początkowo używa DI, aby wykonać właściwą akcję w "trybie na żywo" i użyła Mocks, aby zapewnić rodzaj sterylnego komunikatora, który nie robi ". w ogóle nie robić niczego w trybie testowym.

Widziałem lub czytałem tylko o Mokach używanych w czystym trybie TDD i nie będąc przyzwyczajonym do bycia głupim obiektem. Podejścia, które widziałem, obróciłyby się wokół niedokładności lub szyderstwa funkcji komunikacji HTTP, od której zależą wszystkie interfejsy API, z których korzystam.

Moim głównym zmartwieniem jest to, że wszystkie usługi, z którymi zamierzam się połączyć, wymagałyby dużej ilości szczegółowej pracy zastępującej konkretną implementację HTTP, a gdybym użył metody pośredniej, miałbym 3 klasy dla każda z tych usług (IService, ConcreteService, StubService) i utrzymywanie tych podczas wdrażania nowej metody lub zmiany czegokolwiek będzie prawdziwą PITA.

W obecnej wersji używam Mocks, aby uzyskać "tryb sterylny" za darmo prawie bez konieczności implementowania czegokolwiek dodatkowego tylko po to, aby dostosować się do określonej jednostki testującej.

Pytanie brzmi: czy czegoś brakuje? Czy złamałem zasadę projektu przy użyciu Mocks w bardziej ... wygodny sposób?

Czy ktoś może doradzić, jak uzyskać sterylny tryb z wielu różnych usług zewnętrznych, nie skacząc przez wiele kół?

Czy to pytanie ma sens?

Dzięki za wszystkie odpowiedzi.

Edytuj nr 1:

Nie było jasne w moim pierwotnym pytaniu. Wszelkie obiekty puste lub fałszywe mogą być używane wyłącznie w środowisku programowania/debugowania/testowania. W produkcji kod, który przesyła te wiadomości, będzie faktyczną ich implementacją.

Głosowałem za każdym razem, ponieważ wydaje się, że istnieje wiele różnych rozwiązań tego problemu i będę je badał.

Proszę nie sądzić, że to pytanie zostało już odebrane, będę wdzięczny za radę, jaką mogę uzyskać.

Odpowiedz

6

Istnieje wzór projektu o nazwie Null Object. Obiekt pusty to obiekt, który implementuje interfejs, dlatego może być używany w scenariuszu takim jak twój.

Ważne jest, aby obiekt Null nie zwracał wartości NULL w miejscach, w których może to spowodować uszkodzenie systemu.

Celem obiektu zerowego jest posiadanie pustki i prostej implementacji czegoś, podobnie jak makieta, ale do wykorzystania w środowisku produkcyjnym.

Najprostszym przykładem jest coś takiego:

class Logger{ 
private static ILogger _Logger; 

static Logger(){ 
    //DI injection here 
    _Logger = new NullLogger(); //or 
    _Logger = new TraceLogger(); 
} 
} 

interface ILogger{ 
void Log(string Message); 
} 

internal class TraceLogger:ILooger{ 
public void Log(string Message){ 
    //Code here 
} 
} 

internal class NullLogger{ 
public void Log(string Message){ 
    //Don't don anything, in purporse 
} 
} 

Mam nadzieję, że to może pomóc

+0

Po drugie, gdy zobaczyłem temat tego wątku, pojawił się czerwony alert "Null Object" ... – abyx

4

Myślę, że być może trzeba będzie wyjaśnić swoje pytanie. Nie wiem, czy mówimy o używaniu podwójnych testów w testach bez oczekiwania na stubbing lub testowanie (więc używanie ich jako podróbek, aby spełnić wymagane interfejsy) lub czy mówimy o używaniu makiet w scenariuszu produkcyjnym do wypełnienia dla usług które nie są dostępne (twój rozłączony scenariusz).

Jeśli mówisz o sytuacjach testowych: Moki są testowymi podwójnymi. Nie ma nic złego w testowaniu przy użyciu podróbek, w przeciwieństwie do mocks lub stubów. Jeśli nie potrzebujesz korzystać z usługi w konkretnym teście, to właśnie po to, aby zapewnić dany interfejs, na który obiekt poddawany jest testowi, wówczas jest on w porządku. To nie łamie żadnej głównej kontroli.

Dobre szydercze biblioteki zacierają linie między mockami, stubami i podróbkami.

Zapoznaj się z niektórymi informacjami z Martin Fowler na temat różnych typów podwójnych testów. Mocks Aren't Stubs, TestDoubles.

Bardzo podoba mi się sposób, w jaki moq pozwala na kontinuum pomiędzy sztucznymi, fałszywymi, stubowymi i pozorowanymi obiektami bez konieczności przeskakiwania przez obręcze, aby uzyskać określone zachowania. Check it out.

Jeśli mówisz o używaniu makiet w twoim rozłączonym scenariuszu do użytku produkcyjnego ... Byłbym zmartwiony. Fałszywe będzie zwracanie pustych obiektów lub wartości domyślnych dla wszystkich wykonywanych połączeń. To spowoduje wyciek złożoności do całego kodu zużywającego te usługi (będą one musiały obsłużyć sprawdzanie zerowych wartości zwracanych i pustych tablic ...). Sądzę, że bardziej sensowne byłoby zakodowanie twojego rozłączonego/sterylnego scenariusza, aby poradzić sobie z tym, że same zależności są niedostępne, a nie akceptować fałszywych implementacji i kontynuować, jakby wszystko działało.

4

To brzmi dla mnie jak może chcesz przyjrzeć się strukturze proxy. Chcesz czegoś, co działa jak różne usługi, nawet wtedy, gdy jest odłączone od rzeczywistych usług. Dlatego twój kod lepiej będzie rozmawiać z serwerem proxy zamiast z prawdziwym. Następnie proxy może zrobić, co trzeba, w zależności od bieżącego stanu połączenia.

Powiązane problemy