Mówisz, że Twój kod działa, ale czy na pewno jesteś tego pewny? Wprowadzasz zmianę w kodzie i może czujesz, że twój projekt to tykająca bomba na produkcji. Testy jednostkowe, integracyjne, systemowe, akceptacyjne itp. pozwolą Ci spokojniej spać.  Jeśli natomiast temat testów jednostkowych nie jest za dobrze Ci znany polecam zajrzeć do wcześniejszego mojego wpisu o dobrych praktykach w implementacji testów jednostkowych. Teraz przejdźmy na kolejny poziom wtajemniczenia po testach jednostkowych, czyli testy integracyjne. Testy integracyjne wykonywane są w celu wykrycia defektów w interfejsach i interakcjach pomiędzy modułami.

Microsoft.AspNetCore.TestHost

W wpisie o Fluent Validation z ASP.NET Core Web API zweryfikowałem funkcjonalność API wykorzystując narzędzie Postman. Dzisiaj zautomatyzujemy powyższy proces wykorzystując TestServer i HttpClient. Na początek stwórzmy osobny projekt dla testów integracyjnych, można zastosować jedną z poniższych konwencji nazewnictwa:

  • ApiProjectName.Tests.EndToEnd;
  • ApiProjectName.Tests.Integration;
  • ApiProjectName.IntegrationTests.

Do projektu instalujemy paczkę Microsoft.AspNetCore.TestHost z NuGet. Po dołączeniu zależności możemy tworzyć i konfigurować serwer testowy na potrzeby testów. W celu uniknięcia powielania kodu wydzielę wspólną logikę powtarzającą się dla klas testujących kontrolery do klasy abstrakcyjnej TestBase.

W klasie abstrakcyjnej następuje konfiguracja i inicjalizacja serwera testowego i klienta. Aktualnie mamy możliwość obsługi żądań testowych na testowym hoście, bez konieczności korzystania z prawdziwego hosta.

Testy kontrolera

Czas na napisanie kilku przykładowych testów w xUnit sprawdzających poprawność wywołania API dla kontrolera z wpisu  Fluent Validation z ASP.NET Core Web API.  Do wcześniejszej wersji kontrolera dorzuciłem obsługę asynchroniczności, oraz wstrzykiwanie implementacji IMapper przez konstruktor, poniżej prezentuję aktualną wersję kodu PicturesController.

W testach HttpClient używany jest do tworzenia żądań do testowego serwera i otrzymania odpowiedzi. Przypadek testowy dla żądania GET jest dość prosty, w przypadku żądań POST trzeba przygotować więcej danych. Należy stworzyć obiekt StringContent zawierający model, który dziedziczy po HttpContent.

Udało się TestServer działa i przykładowe testy integracyjne przechodzą.

successStatus

Podsumowanie

W wpisie przedstawiłem jak w prosty sposób można wykonać testy integracyjne kontrolera z wykorzystaniem serwera testowego dla aplikacji ASP.NET Core Web API. Ze względu na zależności do usług testy integracyjne będą wolniejsze od testów jednostkowych,  które są odseparowane. W powyższym przykładzie nie korzystałem bezpośrednio z bazy danych, tylko wykorzystałem po stronie repozytorium zwykłą kolekcje do przechowywania danych. Implementacje testów z bazą danych poruszę innym razem, ten temat czeka na razie na Trello w kolejce do realizacji. Celem testów integracyjnych nie jest zastąpienie testów jednostkowych, stanowią kolejną opcję w procesie testowania, którą warto znać i stosować.