Unit tests frequently miss integration flaws, such as improperly configured Entity Framework mappings, inappropriate routing pathways, invalid JSON serialization settings, or flawed authentication pipelines, even though they validate isolated classes and functions by simulating dependencies.
Integration testing, in which your complete ASP.NET Core Web API boots up in an in-memory test host and executes end-to-end HTTP queries, is necessary to get genuine trust in your application.
This article describes how to use xUnit and WebApplicationFactory to implement integration testing at a production-grade level.
1. Architectural Strategy: The In-Memory Test Server
WebApplicationFactory<TProgram> spins up a real instance of your ASP.NET Core web host in memory without binding to an external port.
- Real Middleware Pipeline: Requests pass through your actual authentication, rate-limiting, routing, and global exception-handling middleware.
- Test Isolation: You can override dependency injection services on-the-fly—for instance, replacing a production database context with an in-memory database or a temporary Testcontainer instance.
2. Step 1: Installing Required Testing NuGet Packages
Create a separate xUnit test project (e.g., WebApi.IntegrationTests) and install the necessary packages:
Shell
dotnet add package Microsoft.AspNetCore.Mvc.Testing
dotnet add package xunit
dotnet add package xunit.runner.visualstudio
dotnet add package FluentAssertions
3. Step 2: Creating a Custom WebApplicationFactory
To isolate your tests from your production database, create a custom factory that replaces your database configuration with an isolated in-memory or SQLite database instance.
C#
// WebApi.IntegrationTests/CustomWebApplicationFactory.cs
using Infrastructure.Persistence;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
namespace WebApi.IntegrationTests;
public class CustomWebApplicationFactory : WebApplicationFactory<Program>
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureServices(services =>
{
// 1. Remove the existing production DbContext registration
var descriptor = services.SingleOrDefault(
d => d.ServiceType == typeof(DbContextOptions<AppDbContext>));
if (descriptor != null)
{
services.Remove(descriptor);
}
// 2. Add a new AppDbContext using an in-memory database for testing
services.AddDbContext<AppDbContext>(options =>
{
options.UseInMemoryDatabase("InMemoryTestDb");
});
// 3. Build the service provider and seed test data
var sp = services.BuildServiceProvider();
using var scope = sp.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
db.Database.EnsureCreated();
// Seed sample data if needed...
});
}
}
4. Step 3: Writing End-to-End Integration Tests
Now, write your xUnit test class leveraging the custom factory to send real HTTP requests using an HttpClient.
C#
// WebApi.IntegrationTests/Controllers/ProductsControllerTests.cs
using System.Net;
using System.Net.Http.Json;
using FluentAssertions;
using Xunit;
namespace WebApi.IntegrationTests.Controllers;
public class ProductsControllerTests : IClassFixture<CustomWebApplicationFactory>
{
private readonly HttpClient _client;
public ProductsControllerTests(CustomWebApplicationFactory factory)
{
// Creates the in-memory HttpClient attached to our test host
_client = factory.CreateClient();
}
[Fact]
public async Task GetById_ReturnsNotFound_WhenProductDoesNotExist()
{
// Arrange
int nonExistentId = 9999;
// Act
var response = await _client.GetAsync($"/api/products/{nonExistentId}");
// Assert
response.StatusCode.Should().Be(HttpStatusCode.NotFound);
}
[Fact]
public async Task CreateProduct_ReturnsCreatedStatusCode_AndValidId()
{
// Arrange
var newProductCommand = new { Name = "Test Widget", Price = 49.99m, Stock = 10 };
// Act
var response = await _client.PostAsJsonAsync("/api/products", newProductCommand);
// Assert
response.StatusCode.Should().Be(HttpStatusCode.Created);
var createdId = await response.Content.ReadFromJsonAsync<int>();
createdId.Should().BeGreaterThan(0);
}
}
Conclusion
By leveraging WebApplicationFactory and xUnit, your integration test suite verifies your actual ASP.NET Core routing, middleware pipelines, model binding, and database logic end-to-end, guaranteeing production readiness before deployment.
Best ASP.NET Core 11.0 Hosting
The feature and reliability are the most important things when choosing a good ASP.NET Core 11.0 hosting. HostForLIFE is the leading provider of Windows hosting and affordable ASP.NET Core , their servers are optimized for PHP web applications such as the latest ASP.NET Core 11.0 version. The performance and the uptime of the ASP.NET Core hosting service are excellent, and the features of the web hosting plan are even greater than what many hosting providers ask you to pay for. At HostForLIFE.eu, customers can also experience fast ASP.NET Core hosting. The company invested a lot of money to ensure the best and fastest performance of the datacenters, servers, network and other facilities. Its data centers are equipped with top equipment like cooling system, fire detection, high-speed Internet connection, and so on. That is why HostForLIFE.eu guarantees 99.9% uptime for ASP.NET Core . And the engineers do regular maintenance and monitoring works to assure its ASP.NET Core hosting are security and always up.

