Podchodzisz do tego niewłaściwie. Po prostu przetestuj swoją funkcjonalność: jeśli zostanie zgłoszony wyjątek, test automatycznie się nie powiedzie. Jeśli nie zostanie zgłoszony żaden wyjątek, wszystkie testy zmienią kolor na zielony.
Od czasu do czasu zauważyłem, że to pytanie wzbudza zainteresowanie, więc trochę poszerzę.
Tło do testów jednostkowych
Podczas testowania jednostkowego ważne jest, aby określić, co uważasz za jednostkę pracy. Zasadniczo: ekstrakcja bazy kodu, która może, ale nie musi zawierać wiele metod lub klas reprezentujących jeden element funkcjonalności.
Lub, zgodnie z definicją w The Art of Unit Testing, 2nd Edition Roy Osherove , strona 11:
Testów jednostkowych jest zautomatyzowany kawałek kodu, który wywołuje jednostka pracy testowane, a następnie sprawdza pewne założenia dotyczące pojedynczego wyniku końcowym tej jednostki. Test jednostkowy prawie zawsze jest pisany przy użyciu frameworka testowego. Można go łatwo napisać i działa szybko. Jest godny zaufania, czytelny i łatwy w utrzymaniu. Jest spójny w wynikach, o ile kod produkcyjny się nie zmienił.
Ważne jest, aby zdawać sobie sprawę, że jedna jednostka pracy zwykle nie jest tylko jedną metodą, ale na bardzo podstawowym poziomie jest jedną metodą, a następnie jest kapsułkowana przez inną jednostkę pracy.
Najlepiej jest mieć metodę testową dla każdej oddzielnej jednostki pracy, aby zawsze można było natychmiast zobaczyć, co się dzieje. W tym przykładzie istnieje podstawowa metoda o nazwiegetUserById()
która zwróci użytkownika, i są w sumie 3 jednostki pracy.
Pierwsza jednostka pracy powinna sprawdzić, czy prawidłowy użytkownik jest zwracany w przypadku prawidłowego i nieprawidłowego wprowadzenia.
Należy tutaj uwzględnić wszelkie wyjątki zgłaszane przez źródło danych: jeśli nie ma żadnego użytkownika, powinien zostać przeprowadzony test wykazujący, że wyjątek jest zgłaszany, gdy nie można go znaleźć. Przykładem może być ten, IllegalArgumentException
który został złapany z @Test(expected = IllegalArgumentException.class)
adnotacją.
Po obsłużeniu wszystkich przypadków użycia dla tej podstawowej jednostki pracy, przechodzisz na wyższy poziom. Tutaj robisz dokładnie to samo, ale radzisz sobie tylko z wyjątkami pochodzącymi z poziomu tuż poniżej bieżącego. Dzięki temu kod testowy jest dobrze ustrukturyzowany i pozwala szybko przeszukać architekturę, aby sprawdzić, gdzie coś pójdzie nie tak, zamiast przeskakiwać wszędzie.
Obsługa prawidłowych i błędnych danych wejściowych testu
W tym momencie powinno być jasne, jak poradzimy sobie z tymi wyjątkami. Istnieją 2 rodzaje danych wejściowych: prawidłowe dane wejściowe i błędne dane wejściowe (dane wejściowe są prawidłowe w ścisłym tego słowa znaczeniu, ale nie są prawidłowe).
Kiedy pracujesz z prawidłowymi danymi wejściowymi, ustawiasz niejawne oczekiwanie, że dowolny test, który napiszesz, zadziała.
Taka metoda połączenie może wyglądać następująco: existingUserById_ShouldReturn_UserObject
. Jeśli ta metoda zawiedzie (np. Zgłoszony zostanie wyjątek), wiesz, że coś poszło nie tak i możesz zacząć kopać.
Dodając kolejny test ( nonExistingUserById_ShouldThrow_IllegalArgumentException
), który wykorzystuje błędne dane wejściowe i oczekuje wyjątku, możesz sprawdzić, czy twoja metoda robi to, co powinna zrobić z nieprawidłowymi danymi wejściowymi.
TL; DR
Próbowałeś zrobić dwie rzeczy w teście: sprawdź, czy dane wejściowe są prawidłowe i błędne. Dzieląc to na dwie metody, z których każda robi jedną rzecz, uzyskasz o wiele jaśniejsze testy i znacznie lepszy przegląd tego, co się nie powiedzie.
Pamiętając o warstwowej jednostce prac, możesz również zmniejszyć liczbę testów potrzebnych dla warstwy znajdującej się wyżej w hierarchii, ponieważ nie musisz uwzględniać wszystkich rzeczy, które mogły pójść nie tak w niższych warstwach: warstwy poniżej bieżącej są wirtualną gwarancją, że twoje zależności działają, a jeśli coś pójdzie nie tak, znajduje się w twojej bieżącej warstwie (zakładając, że niższe warstwy nie powodują żadnych błędów).