Перейти к содержимому
Docs Try Aspire
Docs Try

Advanced testing scenarios

Это содержимое пока не доступно на вашем языке.

This article covers advanced patterns for testing Aspire applications, including selectively disabling resources during tests, overriding environment variables, and customizing the AppHost for specific test scenarios.

When running integration tests, you might want to exclude certain resources to reduce test complexity or cost—for example, disabling a monitoring dashboard or skipping a sidecar resource that isn’t relevant to a particular test.

Use WithExplicitStart to control resource startup

Section titled “Use WithExplicitStart to control resource startup”

The recommended way to make a resource optional is to use WithExplicitStart in the AppHost, and then let tests choose whether to start that resource. Resources marked with WithExplicitStart are created but don’t start automatically with the rest of the application.

In your AppHost, mark the resource as explicitly started:

C# — AppHost.cs
var builder = DistributedApplication.CreateBuilder(args);
var api = builder.AddProject<Projects.Api>("api");
// This resource is optional and won't start automatically
builder.AddContainer("monitoring", "grafana/grafana")
.WithExplicitStart();
builder.Build().Run();

In your test, you can start the resource manually if needed, or leave it stopped:

C# — IntegrationTest.cs
[Fact]
public async Task ApiWorksWithoutMonitoring()
{
var appHost = await DistributedApplicationTestingBuilder
.CreateAsync<Projects.MyAppHost>();
await using var app = await appHost.BuildAsync();
await app.StartAsync();
// The "monitoring" resource is not started—only "api" is running
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
await app.ResourceNotifications.WaitForResourceHealthyAsync("api", cts.Token);
using var httpClient = app.CreateHttpClient("api");
using var response = await httpClient.GetAsync("/health");
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
}

Conditionally add resources based on configuration

Section titled “Conditionally add resources based on configuration”

Another approach is to use configuration in your AppHost to conditionally add resources. This gives tests control over which resources are included:

C# — AppHost.cs
var builder = DistributedApplication.CreateBuilder(args);
var api = builder.AddProject<Projects.Api>("api");
// Only add the database resource if not explicitly disabled
if (builder.Configuration.GetValue("AddDatabase", true))
{
var db = builder.AddPostgres("postgres").AddDatabase("mydb");
api.WithReference(db);
}
builder.Build().Run();

In tests, pass the configuration argument to skip the database:

C# — IntegrationTest.cs
[Fact]
public async Task ApiStartsWithoutDatabase()
{
var appHost = await DistributedApplicationTestingBuilder
.CreateAsync<Projects.MyAppHost>(["AddDatabase=false"]);
// Assert that the "postgres" resource doesn't exist
Assert.DoesNotContain(appHost.Resources, r => r.Name == "postgres");
await using var app = await appHost.BuildAsync();
await app.StartAsync();
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
await app.ResourceNotifications.WaitForResourceAsync(
"api", KnownResourceStates.Running, cts.Token);
}

Resources in Aspire can have wait dependencies (via WaitFor or WaitForCompletion). In some tests, you may want to remove these wait annotations to speed up test startup or to test behavior when dependent resources are unavailable.

You can remove WaitAnnotation instances after building the testing builder, before calling BuildAsync:

C# — IntegrationTest.cs
using Aspire.Hosting.ApplicationModel;
[Fact]
public async Task ApiStartsWithoutWaitingForDatabase()
{
var appHost = await DistributedApplicationTestingBuilder
.CreateAsync<Projects.MyAppHost>();
// Remove wait annotations from all resources so they start immediately
foreach (var resource in appHost.Resources)
{
var waitAnnotations = resource.Annotations.OfType<WaitAnnotation>().ToList();
foreach (var annotation in waitAnnotations)
{
resource.Annotations.Remove(annotation);
}
}
await using var app = await appHost.BuildAsync();
await app.StartAsync();
// Resources start without waiting for dependencies
}

Because Aspire tests run services in separate processes, you can’t inject services directly through dependency injection. However, you can influence application behavior through environment variables or configuration.

Override environment variables via the AppHost builder

Section titled “Override environment variables via the AppHost builder”

Use WithEnvironment on the resource builder after creating the testing builder to set environment variables for specific resources. You access the resource builder through the CreateResourceBuilder method:

C# — IntegrationTest.cs
[Fact]
public async Task ApiUsesTestFeatureFlag()
{
var appHost = await DistributedApplicationTestingBuilder
.CreateAsync<Projects.MyAppHost>();
// Override an environment variable for the "api" resource
appHost.CreateResourceBuilder<ProjectResource>("api")
.WithEnvironment("FeatureFlags__NewCheckout", "true");
await using var app = await appHost.BuildAsync();
await app.StartAsync();
// The "api" service now runs with the overridden feature flag
}

Override configuration with AppHost arguments

Section titled “Override configuration with AppHost arguments”

You can also pass arguments to the AppHost to override configuration values. Arguments are passed to the .NET configuration system, so they can override values from appsettings.json. For more information, see Pass arguments to your AppHost.

Override AppHost configuration before resources are created

Section titled “Override AppHost configuration before resources are created”

For more control over the AppHost configuration before any resources are created, use the DistributedApplicationFactory class and override the OnBuilderCreating lifecycle method. For more information, see Use the DistributedApplicationFactory class.

For full documentation on argument passing and the DistributedApplicationFactory lifecycle, see Manage the AppHost in tests.

The Aspire CLI supports file-based AppHosts — a lightweight apphost.cs file with no .csproj project file. These are created with aspire init or the aspire-apphost-singlefile template and are run directly with aspire run.

The DistributedApplicationTestingBuilder.CreateAsync<T>() method requires a type from the Projects namespace:

C# — IntegrationTest.cs
// This requires Projects.MyAppHost to exist — only available via ProjectReference
var appHost = await DistributedApplicationTestingBuilder
.CreateAsync<Projects.MyAppHost>();

The Projects namespace entries are only generated for <ProjectReference> entries in your test project. A file-based apphost.cs produces no such entry.