Delen via


Eenheids- en integratietests in minimale API-apps

Opmerking

Dit is niet de nieuwste versie van dit artikel. Zie de .NET 9-versie van dit artikel voor de huidige release.

Waarschuwing

Deze versie van ASP.NET Core wordt niet meer ondersteund. Zie het .NET- en .NET Core-ondersteuningsbeleid voor meer informatie. Zie de .NET 9-versie van dit artikel voor de huidige release.

Belangrijk

Deze informatie heeft betrekking op een pre-releaseproduct dat aanzienlijk kan worden gewijzigd voordat het commercieel wordt uitgebracht. Microsoft geeft geen garanties, uitdrukkelijk of impliciet, met betrekking tot de informatie die hier wordt verstrekt.

Zie de .NET 9-versie van dit artikel voor de huidige release.

Door Fiyaz Bin Hasan en Rick Anderson

Inleiding tot integratietests

Integratietests evalueren de onderdelen van een app op een breder niveau dan eenheidstests. Eenheidstests worden gebruikt voor het testen van geïsoleerde softwareonderdelen, zoals afzonderlijke klassemethoden. Integratietests bevestigen dat twee of meer app-onderdelen samenwerken om een verwacht resultaat te produceren, mogelijk inclusief elk onderdeel dat nodig is om een aanvraag volledig te verwerken.

Deze bredere tests worden gebruikt om de infrastructuur en het hele framework van de app te testen, vaak inclusief de volgende onderdelen:

  • gegevensbank
  • Bestandssysteem
  • Netwerkapparaten
  • Pijplijn voor aanvraag-antwoord

Eenheidstests maken gebruik van ge fabriceerde onderdelen, ook wel nep- of mockobjecten genoemd, in plaats van infrastructuuronderdelen.

In tegenstelling tot eenheidstests, integratietests:

  • Gebruik de werkelijke onderdelen die door de app in productie worden gebruikt.
  • Meer code en gegevensverwerking vereisen.
  • Het duurt langer om uit te voeren.

Beperk daarom het gebruik van integratietests tot de belangrijkste infrastructuurscenario's. Als een gedrag kan worden getest met behulp van een eenheidstest of een integratietest, kiest u de eenheidstest.

In discussies over integratietests wordt het geteste project kortom het systeem onder test of 'SUT' genoemd. "SUT" wordt in dit artikel gebruikt om te verwijzen naar de ASP.NET Core-app die wordt getest.

Schrijf geen integratietests voor elke permutatie van gegevens- en bestandstoegang met databases en bestandssystemen. Ongeacht het aantal plaatsen in een app dat communiceert met databases en bestandssystemen, is een gerichte set integratietests voor lezen, schrijven, bijwerken en verwijderen meestal geschikt voor het testen van database- en bestandssysteemonderdelen. Gebruik eenheidstests voor routinetests van methodelogica die met deze onderdelen communiceren. In eenheidstests resulteert het gebruik van infrastructuurvervalsingen of mocks in een snellere testuitvoering.

ASP.NET Kernintegratietests

Integratietests in ASP.NET Core vereisen het volgende:

  • Een testproject wordt gebruikt om de tests te bevatten en uit te voeren. Het testproject heeft een verwijzing naar de SUT.
  • Het testproject maakt een testwebhost voor de SUT en gebruikt een testserverclient voor het afhandelen van aanvragen en antwoorden met de SUT.
  • Een testloper wordt gebruikt om de tests uit te voeren en de testresultaten te rapporteren.

Integratietests volgen een reeks gebeurtenissen die de gebruikelijke teststappen Rangschikken, Act en Assert bevatten:

  1. De webhost van de SUT is geconfigureerd.
  2. Er wordt een testserverclient gemaakt om aanvragen naar de app te verzenden.
  3. De teststap Rangschikken wordt uitgevoerd: De test-app bereidt een aanvraag voor.
  4. De teststap Act wordt uitgevoerd: de client verzendt de aanvraag en ontvangt het antwoord.
  5. De assert-teststap wordt uitgevoerd: het daadwerkelijke antwoord wordt gevalideerd als een geslaagd of mislukt op basis van een verwacht antwoord.
  6. Het proces wordt voortgezet totdat alle tests worden uitgevoerd.
  7. De testresultaten worden gerapporteerd.

Normaal gesproken is de testwebhost anders geconfigureerd dan de normale webhost van de app voor de testuitvoeringen. Een andere database of andere app-instellingen kunnen bijvoorbeeld worden gebruikt voor de tests.

Infrastructuuronderdelen, zoals de testwebhost en de testserver in het geheugen (TestServer), worden geleverd of beheerd door het microsoft.AspNetCore.Mvc.Testing-pakket . Het gebruik van dit pakket stroomlijnt het maken en uitvoeren van tests.

Het Microsoft.AspNetCore.Mvc.Testing pakket verwerkt de volgende taken:

  • Kopieert het afhankelijkhedenbestand (.deps) van de SUT naar de map van bin het testproject.
  • Hiermee stelt u de inhoudshoofdmap in op de hoofdmap van het SUT-project, zodat statische bestanden en pagina's/weergaven worden gevonden wanneer de tests worden uitgevoerd.
  • Biedt de klasse WebApplicationFactory om het bootstrappen van de SUT te stroomlijnen.TestServer

In de documentatie voor eenheidstests wordt beschreven hoe u een testproject en testloper instelt, samen met gedetailleerde instructies voor het uitvoeren van tests en aanbevelingen voor het benoemen van tests en testklassen.

Afzonderlijke eenheidstests van integratietests in verschillende projecten. Het scheiden van de tests:

  • Helpt ervoor te zorgen dat onderdelen voor infrastructuurtests niet per ongeluk worden opgenomen in de eenheidstests.
  • Hiermee kunt u bepalen welke set tests worden uitgevoerd.

De voorbeeldcode op GitHub biedt een voorbeeld van eenheids- en integratietests voor een minimale API-app.

Implementatietypen IResult

Openbare IResult implementatietypen in de Microsoft.AspNetCore.Http.HttpResults naamruimte kunnen worden gebruikt om minimale routehandlers te testen wanneer u benoemde methoden gebruikt in plaats van lambdas.

De volgende code maakt gebruik van de NotFound<TValue>-klasse:

[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);
}

De volgende code maakt gebruik van de Ok<TValue>-klasse:

[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);
}

Aanvullende informatiebronnen