An integration test checks whether independently developed components work correctly when connected. A unit test isolates one unit, often replacing its dependencies with fakes; an integration test exercises selected real implementations together. The scope can be narrow, such as a repository working with a database, or broad, such as an API request passing through several components. section 8.0 section 8.2 section 8.5
Choose real integration points, then control boundaries that would make the test slow or unpredictable:
- Configure the EF Core DbContext through options supplied by the caller. Test the repository against an in-memory SQLite database, seed data, assert stored and retrieved results, and dispose of its resources after the test. section 8.2
- Use the real HTTP client implementation but fake responses through HttpMessageHandler. This keeps the client and its callers in the test without depending on a live website. section 8.1 section 8.6
- For a broader test, construct the application service with the real repository and client. Check the sequence: compare the latest available item with the latest stored item, fetch missing items, save them, then search the repository. section 8.4
- For an ASP.NET Core API, use WebApplicationFactory to issue an HTTP request through the API and its dependencies. Adjust its service registrations, configuration, or environment for the test. section 8.5 section 8.6
Search across an API and its dependencies
Supply fake HTTP responses for three comics, including number 12 with title “b.” Send GET /search?searchText=b through a WebApplicationFactory client. Assert an OK response and a deserialized result containing only comic 12. The request exercises the controller, finder, HTTP client, and repository while the external HTTP responses remain controlled. section 8.5 section 8.4
Listing 8.22 Using WebApplicationFactory
using System.Text.Json;
using ComicFinderService;
using Microsoft.AspNetCore.Mvc.Testing; #1
using Microsoft.Extensions.DependencyInjection; #2
namespace XkcdComicFinder.Tests;
public class SearchControllerTests
{
private const string BaseAddress = "https://xkcd.com";
private readonly WebApplicationFactory<Program> #3
_factory;
private readonly HttpMessageHandler _fakeMsgHandler; #4
public SearchControllerTests()
{
_fakeMsgHandler = A.Fake<HttpMessageHandler>();
_factory = new WebApplicationFactory<Program>() #3
.WithWebHostBuilder(builder =>
{
builder.ConfigureServices(services =>
{
ServiceDescriptor sd = services.First(
s => s.ServiceType == typeof(HttpClient)); #5
services.Remove(sd); #6
services.AddHttpClient<IXkcdClient, XkcdClient>( #7
h => h.BaseAddress = new Uri(BaseAddress))
.ConfigurePrimaryHttpMessageHandler( #8
() => _fakeMsgHandler);
});
});
}
}
The WebApplicationFactory setup shows where the test replaces a registered service so an API request can use a faked HTTP boundary. section 8.5






























