Rilasciato · in miglioramento
Guida a ASP.NET Core · 5/6
Per ora questo capitolo è disponibile solo in inglese.
ASP.NET Core apps are usually tested at two levels: unit tests for services and logic, and integration tests that host the whole app in memory with WebApplicationFactory. xUnit is the most widely used test framework in .NET; NUnit and MSTest work in the same way.
dotnet new xunit -o tests/TodoApi.Tests
dotnet add tests/TodoApi.Tests/TodoApi.Tests.csproj reference src/TodoApi/TodoApi.csproj
dotnet add tests/TodoApi.Tests/TodoApi.Tests.csproj package Microsoft.AspNetCore.Mvc.Testing
dotnet sln add tests/TodoApi.Tests/TodoApi.Tests.csproj
dotnet testdotnet test builds and runs every test project in the solution; editors show the same tests in a test explorer.
Plain classes need no web host at all:
public static class Slug
{
public static string Create(string title) =>
string.Join('-', title.ToLowerInvariant().Split(' ', StringSplitOptions.RemoveEmptyEntries));
}public class SlugTests
{
[Fact]
public void Joins_words_with_hyphens()
{
Assert.Equal("hello-asp-net", Slug.Create("Hello ASP NET"));
}
[Theory]
[InlineData(" spaced out ", "spaced-out")]
[InlineData("One", "one")]
public void Normalizes_input(string input, string expected)
{
Assert.Equal(expected, Slug.Create(input));
}
}[Fact] marks a single test and [Theory] runs the same test for each [InlineData] row. When a service has dependencies, depend on interfaces or abstractions such as TimeProvider so tests can pass fakes, written by hand or with a library like NSubstitute or Moq.
WebApplicationFactory<TEntryPoint> from Microsoft.AspNetCore.Mvc.Testing starts the app on an in-memory test server and hands you an HttpClient. It runs the real Program.cs, configuration and DI, so routing, middleware and serialization are all exercised.
With top-level statements, the compiler-generated Program class is not public. Newer SDKs can generate the declaration below for you; adding it at the end of Program.cs works with every version:
public partial class Program { }using System.Net;
using System.Net.Http.Json;
using Microsoft.AspNetCore.Mvc.Testing;
public class TodoApiTests(WebApplicationFactory<Program> factory)
: IClassFixture<WebApplicationFactory<Program>>
{
[Fact]
public async Task Get_unknown_todo_returns_404()
{
var client = factory.CreateClient();
var response = await client.GetAsync("/todos/999");
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
}
[Fact]
public async Task Post_then_get_returns_the_todo()
{
var client = factory.CreateClient();
var created = await client.PostAsJsonAsync("/todos", new { title = "Write tests" });
created.EnsureSuccessStatusCode();
var todo = await created.Content.ReadFromJsonAsync<Todo>();
var fetched = await client.GetFromJsonAsync<Todo>($"/todos/{todo!.Id}");
Assert.Equal("Write tests", fetched!.Title);
}
}IClassFixture creates one app per test class and shares it between that class's tests, so tests should not depend on each other's data.
Derive from WebApplicationFactory to choose the environment or replace services. ConfigureTestServices runs after the app's own registrations:
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Time.Testing;
public class TodoApiFactory : WebApplicationFactory<Program>
{
public FakeTimeProvider Time { get; } = new();
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.UseEnvironment("Testing");
builder.ConfigureTestServices(services =>
{
services.RemoveAll<TimeProvider>();
services.AddSingleton<TimeProvider>(Time);
});
}
}FakeTimeProvider comes from the Microsoft.Extensions.TimeProvider.Testing package; tests call Time.Advance(...) to move the clock. For the database, point the Testing environment at a throwaway database, or start a real one in Docker with Testcontainers.
dotnet test --filter "FullyQualifiedName~TodoApiTests"
dotnet test --collect:"XPlat Code Coverage"dotnet new xunit and run it with dotnet test.WebApplicationFactory<Program> hosts the real app in memory for integration tests.ConfigureTestServices.
0 commenti
Accedi · Accedi per lasciare un commento.
Scrivi tu il primo commento.