Testa ASP.NET Core-tjänster och webbappar
Dricks
Det här innehållet är ett utdrag från eBook, .NET Microservices Architecture for Containerized .NET Applications, tillgängligt på .NET Docs eller som en kostnadsfri nedladdningsbar PDF som kan läsas offline.
Styrenheter är en central del av alla ASP.NET Core API-tjänsten och ASP.NET MVC-webbprogram. Därför bör du ha förtroende för att de beter sig som avsett för ditt program. Automatiserade tester kan ge dig detta förtroende och kan identifiera fel innan de når produktion.
Du måste testa hur kontrollanten beter sig baserat på giltiga eller ogiltiga indata och testkontrollantsvar baserat på resultatet av den affärsåtgärd som den utför. Du bör dock ha dessa typer av tester för dina mikrotjänster:
Enhetstester. Dessa tester säkerställer att enskilda komponenter i programmet fungerar som förväntat. Försäkran testar komponent-API:et.
Integreringstester. Dessa tester säkerställer att komponentinteraktioner fungerar som förväntat mot externa artefakter som databaser. Intyg kan testa komponent-API, användargränssnitt eller biverkningar av åtgärder som databas-I/O, loggning osv.
Funktionella tester för varje mikrotjänst. Dessa tester säkerställer att programmet fungerar som förväntat från användarens perspektiv.
Tjänsttester. Dessa tester säkerställer att användningsfall från slutpunkt till slutpunkt, inklusive testning av flera tjänster samtidigt, testas. För den här typen av testning måste du förbereda miljön först. I det här fallet innebär det att du startar tjänsterna (till exempel genom att använda docker-compose up).
Implementera enhetstester för ASP.NET Core-webb-API:er
Enhetstestning omfattar testning av en del av ett program isolerat från dess infrastruktur och beroenden. När du använder teststyrenhetslogik testas endast innehållet i en enskild åtgärd eller metod, inte beteendet för dess beroenden eller själva ramverket. Enhetstester identifierar inte problem i interaktionen mellan komponenter – det är syftet med integreringstestning.
När du testar kontrollantåtgärderna ser du till att du bara fokuserar på deras beteende. Ett kontrollantenhetstest undviker saker som filter, routning eller modellbindning (mappning av begärandedata till en ViewModel eller DTO). Eftersom de fokuserar på att bara testa en sak är enhetstester i allmänhet enkla att skriva och köra snabbt. En välskriven uppsättning enhetstester kan köras ofta utan större omkostnader.
Enhetstester implementeras baserat på testramverk som xUnit.net, MSTest, Moq eller NUnit. För exempelprogrammet eShopOnContainers använder vi xUnit.
När du skriver ett enhetstest för en webb-API-kontrollant instansierar du kontrollantklassen direkt med det nya nyckelordet i C#, så att testet körs så snabbt som möjligt. I följande exempel visas hur du gör detta när du använder xUnit som testramverk.
[Fact]
public async Task Get_order_detail_success()
{
//Arrange
var fakeOrderId = "12";
var fakeOrder = GetFakeOrder();
//...
//Act
var orderController = new OrderController(
_orderServiceMock.Object,
_basketServiceMock.Object,
_identityParserMock.Object);
orderController.ControllerContext.HttpContext = _contextMock.Object;
var actionResult = await orderController.Detail(fakeOrderId);
//Assert
var viewResult = Assert.IsType<ViewResult>(actionResult);
Assert.IsAssignableFrom<Order>(viewResult.ViewData.Model);
}
Implementera integrerings- och funktionstester för varje mikrotjänst
Som nämnts har integreringstester och funktionella tester olika syften och mål. Men sättet du implementerar både när du testar ASP.NET Core-styrenheter är liknande, så i det här avsnittet koncentrerar vi oss på integreringstester.
Integreringstestning säkerställer att ett programs komponenter fungerar korrekt när de monteras. ASP.NET Core stöder integreringstestning med hjälp av enhetstestramverk och en inbyggd testwebbvärd som kan användas för att hantera begäranden utan nätverkskostnader.
Till skillnad från enhetstestning omfattar integreringstester ofta problem med programinfrastruktur, till exempel en databas, ett filsystem, nätverksresurser eller webbbegäranden och svar. Enhetstester använder förfalskningar eller falska objekt i stället för dessa problem. Men syftet med integreringstester är att bekräfta att systemet fungerar som förväntat med dessa system, så för integreringstestning använder du inte förfalskningar eller falska objekt. I stället inkluderar du infrastrukturen, till exempel databasåtkomst eller tjänstanrop från andra tjänster.
Eftersom integreringstester använder större kodsegment än enhetstester, och eftersom integreringstester är beroende av infrastrukturelement, tenderar de att vara storleksordningar långsammare än enhetstester. Därför är det en bra idé att begränsa hur många integreringstester du skriver och kör.
ASP.NET Core innehåller en inbyggd testwebbvärd som kan användas för att hantera HTTP-begäranden utan nätverkskostnader, vilket innebär att du kan köra dessa tester snabbare än när du använder en riktig webbvärd. Testwebbvärden (TestServer) är tillgänglig i en NuGet-komponent som Microsoft.AspNetCore.TestHost. Den kan läggas till i integreringstestprojekt och användas som värd för ASP.NET Core-program.
Som du ser i följande kod instansierar du kontrollanterna via testvärden när du skapar integreringstester för ASP.NET Core-styrenheter. Den här funktionen är jämförbar med en HTTP-begäran, men den körs snabbare.
public class PrimeWebDefaultRequestShould
{
private readonly TestServer _server;
private readonly HttpClient _client;
public PrimeWebDefaultRequestShould()
{
// Arrange
_server = new TestServer(new WebHostBuilder()
.UseStartup<Startup>());
_client = _server.CreateClient();
}
[Fact]
public async Task ReturnHelloWorld()
{
// Act
var response = await _client.GetAsync("/");
response.EnsureSuccessStatusCode();
var responseString = await response.Content.ReadAsStringAsync();
// Assert
Assert.Equal("Hello World!", responseString);
}
}
Ytterligare resurser
Steve Smith. Testa kontrollanter (ASP.NET Core)
https://learn.microsoft.com/aspnet/core/mvc/controllers/testingSteve Smith. Integreringstestning (ASP.NET Core)
https://learn.microsoft.com/aspnet/core/test/integration-testsEnhetstestning i .NET med dotnet-test
https://learn.microsoft.com/dotnet/core/testing/unit-testing-with-dotnet-testxUnit.net. Officiell webbplats.
https://xunit.net/Grunderna för enhetstest.
https://learn.microsoft.com/visualstudio/test/unit-test-basicsMoq. GitHub-lagringsplats.
https://github.com/moq/moqNUnit. Officiell webbplats.
https://nunit.org/
Implementera tjänsttester i ett program med flera containrar
Som tidigare nämnts måste alla mikrotjänster köras i Docker-värden eller containerklustret när du testar program med flera containrar. Tjänsttester från slutpunkt till slutpunkt som omfattar flera åtgärder som omfattar flera mikrotjänster kräver att du distribuerar och startar hela programmet i Docker-värden genom att köra docker-compose up (eller en jämförbar mekanism om du använder en orchestrator). När hela programmet och alla dess tjänster körs kan du köra integrerings- och funktionstester från slutpunkt till slutpunkt.
Det finns några metoder som du kan använda. I den docker-compose.yml fil som du använder för att distribuera programmet på lösningsnivå kan du expandera startpunkten för att använda dotnet-test. Du kan också använda en annan skrivfil som skulle köra dina tester i den avbildning som du riktar in dig på. Genom att använda en annan skrivfil för integreringstester som innehåller dina mikrotjänster och databaser på containrar kan du se till att relaterade data alltid återställs till sitt ursprungliga tillstånd innan du kör testerna.
När kompileringsprogrammet är igång kan du dra nytta av brytpunkter och undantag om du kör Visual Studio. Eller så kan du köra integreringstesterna automatiskt i din CI-pipeline i Azure DevOps Services eller något annat CI/CD-system som stöder Docker-containrar.
Testning i eShopOnContainers
Referensprogramtesterna (eShopOnContainers) har nyligen omstrukturerats och det finns nu fyra kategorier:
Enhetstester, helt enkelt gamla vanliga enhetstester, som finns i {MicroserviceName}. UnitTests-projekt
Funktions-/integreringstester för mikrotjänster, med testfall som involverar infrastrukturen för varje mikrotjänst men som är isolerad från de andra och som finns i {MicroserviceName}. FunctionalTests-projekt .
Funktions-/integreringstester för program, som fokuserar på integrering av mikrotjänster, med testfall som utövar flera mikrotjänster. Dessa tester finns i projektet Application.FunctionalTests.
Även om enhets- och integreringstester ordnas i en testmapp i mikrotjänstprojektet, hanteras program- och belastningstester separat under rotmappen, enligt bild 6–25.
Bild 6-25. Testa mappstrukturen i eShopOnContainers
Funktions-/integreringstester för mikrotjänster och program körs från Visual Studio med hjälp av den vanliga testköraren, men först måste du starta nödvändiga infrastrukturtjänster med en uppsättning docker-compose-filer i lösningstestmappen:
docker-compose-test.yml
version: '3.4'
services:
redis.data:
image: redis:alpine
rabbitmq:
image: rabbitmq:3-management-alpine
sqldata:
image: mcr.microsoft.com/mssql/server:2017-latest
nosqldata:
image: mongo
docker-compose-test.override.yml
version: '3.4'
services:
redis.data:
ports:
- "6379:6379"
rabbitmq:
ports:
- "15672:15672"
- "5672:5672"
sqldata:
environment:
- SA_PASSWORD=[PLACEHOLDER]
- ACCEPT_EULA=Y
ports:
- "5433:1433"
nosqldata:
ports:
- "27017:27017"
Viktigt!
Microsoft rekommenderar att du använder det säkraste tillgängliga autentiseringsflödet. Om du ansluter till Azure SQL är hanterade identiteter för Azure-resurser den rekommenderade autentiseringsmetoden.
För att köra funktions-/integreringstesterna måste du därför först köra det här kommandot från mappen lösningstest:
docker-compose -f docker-compose-test.yml -f docker-compose-test.override.yml up
Som du ser startar dessa docker-compose-filer bara redis-, RabbitMQ-, SQL Server- och MongoDB-mikrotjänster.
Ytterligare resurser
Enhets- och integrationstestning på eShopOnContainers
https://github.com/dotnet-architecture/eShopOnContainers/wiki/Unit-and-integration-testingBelastningstestning på eShopOnContainers
https://github.com/dotnet-architecture/eShopOnContainers/wiki/Load-testing