This example demonstrates how to use HttpMock to mock a downstream API when integration-testing a .NET Aspire distributed application.
A WeatherApi service exposes a /weatherforecast endpoint that internally calls an external weather API (/api/weather). In production, this would be a real third-party service. During integration testing, HttpMock stands in for the external dependency, returning canned responses so tests are fast, deterministic, and don't require network access.
┌──────────────────┐ ┌──────────────────────┐
│ Test Runner │────────▶│ WeatherApi │
│ (NUnit + Aspire │ │ /weatherforecast │
│ Hosting.Testing) │ │ │
└──────────────────┘ └─────────┼──────────────┘
│ HttpClient
▼
┌──────────────────────┐
│ HttpMock Server │
│ /api/weather │
│ (stubbed responses) │
└──────────────────────┘
| Project | Description |
|---|---|
AspireExample.AppHost |
Aspire orchestrator. Registers the WeatherApi and an HttpMockResource via AddHttpMock. |
AspireExample.WeatherApi |
Minimal API that calls a downstream weather service via HttpClient. The base address is read from the ExternalWeatherApi connection string. |
AspireExample.ServiceDefaults |
Shared Aspire service defaults (OpenTelemetry, health checks, resilience, service discovery). |
AspireExample.Tests |
NUnit integration tests using Aspire.Hosting.Testing and HttpMock.Aspire.Hosting. |
The HttpMock.Aspire.Hosting package lets you register an HttpMock stub server as a proper Aspire resource. Aspire starts the server automatically, shows it on the dashboard, and injects its URL into dependent projects — no manual port allocation required.
using HttpMock.Aspire.Hosting;
var builder = DistributedApplication.CreateBuilder(args);
var externalWeatherApi = builder.AddHttpMock("ExternalWeatherApi");
builder.AddProject<Projects.AspireExample_WeatherApi>("weatherapi")
.WithReference(externalWeatherApi);
builder.Build().Run();WithReference automatically injects ConnectionStrings__ExternalWeatherApi = http://localhost:<port> into the WeatherApi process — exactly what it reads via GetConnectionString("ExternalWeatherApi").
builder.Services.AddHttpClient("ExternalWeatherApi", client =>
{
client.BaseAddress = new Uri(
builder.Configuration.GetConnectionString("ExternalWeatherApi")
?? "http://localhost:5200");
});// OneTimeSetUp — get the resource that Aspire already started
var mockResource = _app.Services
.GetRequiredService<DistributedApplicationModel>()
.Resources
.OfType<HttpMockResource>()
.Single(r => r.Name == "ExternalWeatherApi");
_mockServer = mockResource.MockServer!;
// Each test — swap stubs without rebuilding the app
_mockServer.WithNewContext()
.Stub(x => x.Get("/api/weather"))
.Return(jsonPayload)
.AsContentType("application/json")
.OK();
var response = await _httpClient.GetAsync("/weatherforecast");- .NET 10 SDK or later
- A development environment that supports Aspire's DCP (Developer Compute Platform). This is included in the
Aspire.Hosting.AppHostSDK NuGet package.
# Build
dotnet build
# Run the tests
dotnet testThe example includes three integration tests:
| Test | What it demonstrates |
|---|---|
GetWeatherForecast_ReturnsMockedData |
Basic stub: HttpMock returns a JSON array, the WeatherApi forwards it to the caller. |
GetWeatherForecast_WhenDownstreamReturns500_ReturnsError |
Error simulation: HttpMock returns HTTP 500, verifying the WeatherApi propagates the failure. |
GetWeatherForecast_WithDelayedResponse_StillReturnsData |
Slow service simulation: HttpMock adds a 500ms delay via WithDelay(), verifying the WeatherApi still returns data. |