Udostępnij za pośrednictwem


Testy jednostkowe i integracyjne w minimalnych aplikacjach interfejsu API

Uwaga

Nie jest to najnowsza wersja tego artykułu. Aby zapoznać się z bieżącą wersją, zapoznaj się z wersją tego artykułu platformy .NET 8.

Ostrzeżenie

Ta wersja ASP.NET Core nie jest już obsługiwana. Aby uzyskać więcej informacji, zobacz .NET i .NET Core Support Policy (Zasady obsługi platformy .NET Core). Aby zapoznać się z bieżącą wersją, zapoznaj się z wersją tego artykułu platformy .NET 8.

Ważne

Te informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany, zanim zostanie wydany komercyjnie. Firma Microsoft nie udziela żadnych gwarancji, jawnych lub domniemanych, w odniesieniu do informacji podanych w tym miejscu.

Aby zapoznać się z bieżącą wersją, zapoznaj się z wersją tego artykułu platformy .NET 8.

Przez Fiyaz Bin Hasan i Rick Anderson

Wprowadzenie do testów integracji

Testy integracji oceniają składniki aplikacji na szerszym poziomie niż testy jednostkowe. Testy jednostkowe służą do testowania izolowanych składników oprogramowania, takich jak poszczególne metody klasy. Testy integracji potwierdzają, że co najmniej dwa składniki aplikacji współpracują ze sobą, aby wygenerować oczekiwany wynik, prawdopodobnie włącznie z każdym składnikiem wymaganym do pełnego przetworzenia żądania.

Te szersze testy służą do testowania infrastruktury aplikacji i całej struktury, często w tym następujących składników:

  • baza danych
  • System plików
  • Urządzenia sieciowe
  • Potok żądania odpowiedzi

Testy jednostkowe używają sfabrykowanych składników, znanych jako fałszywe lub makiety obiektów, zamiast składników infrastruktury.

W przeciwieństwie do testów jednostkowych, testy integracji:

  • Użyj rzeczywistych składników używanych przez aplikację w środowisku produkcyjnym.
  • Wymagaj więcej kodu i przetwarzania danych.
  • Uruchamianie trwa dłużej.

W związku z tym ogranicz użycie testów integracji do najważniejszych scenariuszy infrastruktury. Jeśli zachowanie można przetestować przy użyciu testu jednostkowego lub testu integracji, wybierz test jednostkowy.

W dyskusjach na temat testów integracji testowany projekt jest często nazywany systemowym testem lub "SUT" w skrócie. Element "SUT" jest używany w tym artykule do odwoływania się do testowanej aplikacji ASP.NET Core.

Nie zapisuj testów integracji dla każdej permutacji danych i dostępu do plików za pomocą baz danych i systemów plików. Niezależnie od liczby miejsc w aplikacji współdziała z bazami danych i systemami plików, skoncentrowany zestaw testów integracji odczytu, zapisu, aktualizacji i usuwania zwykle umożliwia odpowiednie testowanie składników bazy danych i systemu plików. Używaj testów jednostkowych do rutynowych testów logiki metod, które wchodzą w interakcje z tymi składnikami. W testach jednostkowych użycie fałszywych lub pozorów infrastruktury skutkuje szybszym wykonaniem testu.

testy integracji ASP.NET Core

Testy integracji w programie ASP.NET Core wymagają następujących elementów:

  • Projekt testowy służy do zawierania i wykonywania testów. Projekt testowy zawiera odwołanie do sutu.
  • Projekt testowy tworzy testowego hosta internetowego dla sut i używa klienta serwera testowego do obsługi żądań i odpowiedzi przy użyciu sut.
  • Moduł uruchamiający testy służy do wykonywania testów i zgłaszania wyników testu.

Testy integracji są zgodne z sekwencją zdarzeń obejmujących zwykłe kroki testu Rozmieszczanie, Działanie i Asercja :

  1. Host internetowy SUT jest skonfigurowany.
  2. Klient serwera testowego jest tworzony w celu przesyłania żądań do aplikacji.
  3. Krok Rozmieść test jest wykonywany: aplikacja testowa przygotowuje żądanie.
  4. Krok testu aktu jest wykonywany: klient przesyła żądanie i odbiera odpowiedź.
  5. Krok testu potwierdzenia jest wykonywany: rzeczywista odpowiedź jest weryfikowana jako powodzenie lub niepowodzenie w oparciu o oczekiwaną odpowiedź.
  6. Proces będzie kontynuowany do momentu wykonania wszystkich testów.
  7. Wyniki testów są zgłaszane.

Zazwyczaj testowy host internetowy jest skonfigurowany inaczej niż normalny host internetowy aplikacji na potrzeby przebiegów testu. Na przykład do testów mogą być używane różne ustawienia bazy danych lub różnych aplikacji.

Składniki infrastruktury, takie jak testowy host internetowy i serwer testowy w pamięci (TestServer), są dostarczane lub zarządzane przez pakiet Microsoft.AspNetCore.Mvc.Testing . Użycie tego pakietu usprawnia tworzenie i wykonywanie testów.

Pakiet Microsoft.AspNetCore.Mvc.Testing obsługuje następujące zadania:

  • Kopiuje plik zależności (.deps) z sutu do katalogu projektu testowego bin .
  • Ustawia katalog główny zawartości na katalog główny projektu SUT, tak aby pliki statyczne i strony/widoki zostały znalezione podczas wykonywania testów.
  • Udostępnia klasę WebApplicationFactory , aby usprawnić uruchamianie aplikacji SUT za pomocą polecenia TestServer.

W dokumentacji testów jednostkowych opisano sposób konfigurowania projektu testowego i modułu uruchamiającego testy oraz szczegółowe instrukcje dotyczące uruchamiania testów i zaleceń dotyczących sposobu nazywania testów i klas testowych.

Oddziel testy jednostkowe od testów integracji do różnych projektów. Oddzielanie testów:

  • Pomaga zagwarantować, że składniki testowania infrastruktury nie zostaną przypadkowo uwzględnione w testach jednostkowych.
  • Umożliwia kontrolę nad tym, który zestaw testów jest uruchamiany.

Przykładowy kod w usłudze GitHub zawiera przykład testów jednostkowych i integracyjnych w aplikacji interfejsu API Minimum.

Typy implementacji IResult

Publiczne IResult typy implementacji w Microsoft.AspNetCore.Http.HttpResults przestrzeni nazw mogą służyć do testowania jednostkowego minimalnych procedur obsługi tras w przypadku używania nazwanych metod zamiast lambd.

Poniższy kod używa NotFound<TValue> klasy :

[Fact]
public async Task GetTodoReturnsNotFoundIfNotExists()
{
    // Arrange
    await using var context = new MockDb().CreateDbContext();

    // Act
    var result = await TodoEndpointsV1.GetTodo(1, context);

    //Assert
    Assert.IsType<Results<Ok<Todo>, NotFound>>(result);

    var notFoundResult = (NotFound) result.Result;

    Assert.NotNull(notFoundResult);
}

Poniższy kod używa Ok<TValue> klasy :

[Fact]
public async Task GetTodoReturnsTodoFromDatabase()
{
    // Arrange
    await using var context = new MockDb().CreateDbContext();

    context.Todos.Add(new Todo
    {
        Id = 1,
        Title = "Test title",
        Description = "Test description",
        IsDone = false
    });

    await context.SaveChangesAsync();

    // Act
    var result = await TodoEndpointsV1.GetTodo(1, context);

    //Assert
    Assert.IsType<Results<Ok<Todo>, NotFound>>(result);

    var okResult = (Ok<Todo>)result.Result;

    Assert.NotNull(okResult.Value);
    Assert.Equal(1, okResult.Value.Id);
}

Dodatkowe zasoby