ASP.NET Core Web API

Integration Testing (WebApplicationFactory)

1 Views Updated 5/4/2026

Integration Testing (WebApplicationFactory)

While Unit Tests are fast, they operate in an imaginary mocked universe. They cannot catch issues like broken Routing, failing JWT Middleware, or malformed JSON serialization. Integration Testing physically boots up your entire API server in memory, connects a synthetic HttpClient, and fires real network requests against it.

1. Setup WebApplicationFactory

Microsoft provides the Microsoft.AspNetCore.Mvc.Testing package to facilitate this. It spins up an in-memory TestServer using your actual Program.cs.

dotnet add package Microsoft.AspNetCore.Mvc.Testing

2. Writing the Integration Test

We use WebApplicationFactory<Program> to boot the app, and generate an HttpClient that routes directly to the in-memory server.

using Microsoft.AspNetCore.Mvc.Testing;
using Xunit;
using System.Net;

// IClassFixture ensures the server boots up ONCE for all tests in this class to save time
public class UsersIntegrationTests : IClassFixture<WebApplicationFactory<Program>>
{
    private readonly HttpClient _client;

    public UsersIntegrationTests(WebApplicationFactory<Program> factory)
    {
        // Creates a client that points directly to the in-memory API
        _client = factory.CreateClient();
    }

    [Fact]
    public async Task GetAllUsers_ReturnsSuccessStatusCode_AndCorrectContentType()
    {
        // ACT: Fire a physical network request
        var response = await _client.GetAsync("/api/users");

        // ASSERT: Verify 200-299 Status Code
        response.EnsureSuccessStatusCode(); 
        
        // ASSERT: Verify it returned JSON, not XML or HTML
        Assert.Equal("application/json; charset=utf-8", 
            response.Content.Headers.ContentType.ToString());
    }
}

3. Swapping out the Database for Testing

You cannot let your Integration Tests hit your real Production SQL Server! You must configure the WebApplicationFactory to intercept the EF Core DbContext and replace it with an In-Memory Database specifically for testing.

public class CustomWebApplicationFactory : WebApplicationFactory<Program>
{
    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder.ConfigureServices(services =>
        {
            // 1. Find the existing SQL Server DbContext registration
            var descriptor = services.SingleOrDefault(
                d => d.ServiceType == typeof(DbContextOptions<ApplicationDbContext>));

            // 2. Remove it
            if (descriptor != null) services.Remove(descriptor);

            // 3. Inject a safe In-Memory Database instead!
            services.AddDbContext<ApplicationDbContext>(options =>
            {
                options.UseInMemoryDatabase("IntegrationTestDb");
            });
        });
    }
}

4. Interview Mastery

Q: "Extensive Integration Testing seems to verify the same logic as Unit Testing but provides more real-world confidence. Should we abandon Unit Testing and exclusively write Integration Tests using WebApplicationFactory?"

Architect Answer: "No, this violates the 'Test Pyramid'. Integration Tests are 'Heavy'. Booting the in-memory server and running EF Core (even an In-Memory DB) takes hundreds of milliseconds per test. A suite of 5,000 unit tests runs in 3 seconds. A suite of 5,000 integration tests takes 15 minutes. This slows down the CI/CD pipeline and frustrates developers. Furthermore, when an Integration Test fails, diagnosing the cause is difficult because the entire pipeline (Auth, Routing, DB, Serilog) was involved. Unit Tests should comprise 80% of your suite to verify pure business logic instantly, while Integration Tests make up 20% to verify the components connect properly."

ASP.NET Core Web API
1. Fundamentals & HTTP
Introduction to ASP.NET Core Web API REST Principles and HTTP Methods Controllers & ControllerBase Routing (Attribute vs Conventional) Action Return Types (IActionResult)
2. Request Handling
Model Binding (FromQuery, FromBody, FromRoute) Dependency Injection (DI) Deep Dive App Settings & The Options Pattern
3. Data Access & Architecture
EF Core Setup in Web API DbContext & Migrations Repository & Unit of Work Pattern Asynchronous Programming (async/await)
4. Data Transfer & Validation
Data Transfer Objects (DTOs) & AutoMapper Model Validation (DataAnnotations) FluentValidation Integration
5. Advanced Concepts
Global Exception Handling Middleware Content Negotiation (JSON vs XML) Pagination & Filtering Advanced Searching & Sorting HATEOAS (Hypermedia) Implementation Output Caching & Response Caching
6. Security & Authorization
Cross-Origin Resource Sharing (CORS) JWT Authentication Setup Access Tokens & Refresh Tokens Workflow Role-Based & Policy-Based Authorization API Key Authentication Rate Limiting & Throttling
7. Documentation & Testing
Swagger & OpenAPI Configuration Customizing API Documentation Unit Testing Controllers (xUnit & Moq) Integration Testing (WebApplicationFactory)
8. Microservices & Deployment
Consuming External APIs (IHttpClientFactory) Health Checks & Diagnostics API Versioning Strategies Deploying APIs (Docker & Azure)