Overview
Codebelt.Extensions.Xunit.Hosting.AspNetCore extends Codebelt.Extensions.Xunit.Hosting with ASP.NET Core TestServer support. It provides base classes, fixtures, and factories that let you test middleware, services, and endpoints against an in-process HTTP pipeline without starting a real server. The package supports both the classic IHostBuilder hosting model and the modern minimal hosting model (WebApplication), and integrates with xUnit class fixtures so a single application host can be shared across multiple test methods in a class.
The package also provides WebApplicationTestFactory and WebApplicationTest<TEntryPoint, T> for bootstrapping an existing ASP.NET Core application entry point directly in tests. This approach uses BlockingManagedWebApplicationFixture<TEntryPoint> to resolve and start the application host from the entry point assembly, giving tests access to a started TestServer that exercises the real application pipeline.
Key APIs
WebApplicationTestFactory provides static methods for bootstrapping an existing ASP.NET Core application entry point in tests. Create<TEntryPoint>() returns an IHostTest whose Host property exposes a started TestServer, while RunAsync<TEntryPoint>() combines creation with an HTTP request and returns the HttpResponseMessage directly. Both accept an optional Action<IWebHostBuilder> to override host configuration before the application builds.
WebApplicationTest<TEntryPoint, T> is the abstract base class for class-fixture-based entry-point testing. It inherits from HostTest and implements IClassFixture<T>, giving each test class a shared TestServer and IHost. The Server property provides the TestServer instance, and the ConfigureWebHost(IWebHostBuilder) virtual method lets derived tests override host configuration. The generic constraint requires T to implement IWebApplicationFixture<TEntryPoint>.
BlockingManagedWebApplicationFixture<TEntryPoint> implements IWebApplicationFixture<TEntryPoint> and starts the resolved application host synchronously during ConfigureHost. It exposes ConfigureWebHostCallback for host builder overrides and a Server property containing the TestServer. This fixture validates that the caller is a WebApplicationTest<TEntryPoint, T> before building the host.
WebHostTestFactory provides static methods for the classic IHostBuilder hosting pattern. Create() and RunAsync() accept Action<IServiceCollection>, Action<IApplicationBuilder>, and Action<IHostBuilder> delegates for configuring services, middleware pipeline, and host builder respectively. Variants with HostBuilderContext are available via CreateWithHostBuilderContext() and RunWithHostBuilderContextAsync().
MinimalWebHostTestFactory provides the same factory shape for the modern minimal hosting pattern. Its methods accept Action<IHostApplicationBuilder> instead of Action<IHostBuilder>, matching the WebApplicationBuilder style. Internally it creates a WebApplicationBuilder, configures UseTestServer, and builds the host.
WebHostTest<T> is the abstract base class for classic hosting tests using a class fixture. It inherits from HostTest<T> and requires derived classes to implement ConfigureApplication(IApplicationBuilder). The Application property exposes the configured IApplicationBuilder.
MinimalWebHostTest<T> is the abstract base class for minimal hosting tests using a class fixture. It inherits from MinimalHostTest and requires ConfigureApplication(IApplicationBuilder). It accepts IWebMinimalHostFixture implementations and exposes both Application and the inherited Host properties.
Basic usage
using Codebelt.Extensions.Xunit;
using Codebelt.Extensions.Xunit.Hosting.AspNetCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Xunit;
namespace MyProject.Tests;
public class MiddlewareTest : Test
{
public MiddlewareTest(ITestOutputHelper output) : base(output)
{
}
[Fact]
public async Task InvokeAsync_WithRegisteredService_ShouldReturnServiceResponse()
{
using var response = await WebHostTestFactory.RunAsync(
services =>
{
services.AddSingleton(new StatusService("operational"));
},
app =>
{
app.Run(async context =>
{
var status = context.RequestServices.GetRequiredService<StatusService>();
await context.Response.WriteAsync(status.Message);
});
});
var body = await response.Content.ReadAsStringAsync();
TestOutput.WriteLine($"Response status: {response.StatusCode}");
TestOutput.WriteLine($"Response body: {body}");
Assert.True(response.IsSuccessStatusCode);
Assert.Equal("operational", body);
}
private sealed class StatusService
{
public StatusService(string message) => Message = message;
public string Message { get; }
}
}
Use this pattern when you need to verify that middleware, services, or endpoints behave correctly against a real ASP.NET Core pipeline without starting a network listener. When you only need to test plain services or domain logic without an HTTP pipeline, Codebelt.Extensions.Xunit.Hosting or the base Codebelt.Extensions.Xunit package is the lighter choice.
Installation
dotnet add package Codebelt.Extensions.Xunit.Hosting.AspNetCore
Usage guidance
This package is the right choice when your tests need to exercise ASP.NET Core middleware, filters, or endpoint routing through an in-process TestServer. The factory methods (WebHostTestFactory.RunAsync, MinimalWebHostTestFactory.RunAsync, WebApplicationTestFactory.RunAsync) work well for isolated, single-method integration tests, while the class-fixture base classes (WebApplicationTest<TEntryPoint, T>, WebHostTest<T>, MinimalWebHostTest<T>) share a host across an entire test class. If your tests do not depend on an HTTP pipeline or ASP.NET Core services, the base Codebelt.Extensions.Xunit.Hosting package provides the DI and host fixture infrastructure without the TestServer dependency.
