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.
Create a test project
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 test
dotnet test builds and runs every test project in the solution; editors show the same tests in a test explorer.
Unit tests
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.
Integration tests with WebApplicationFactory
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);
}
}
0 commentaire
Se connecter · Connectez-vous pour laisser un commentaire.