Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
aaronontheweb avatar

Aspire Integration Testing

  • 376 installs
  • 1.1k repo stars
  • Updated July 3, 2026
  • aaronontheweb/dotnet-skills

aspire-integration-testing is a .NET agent skill that teaches writing xUnit integration tests for Aspire distributed applications using DistributedApplicationTestingBuilder, real containerized dependencies, and dynamic e

About

aspire-integration-testing is an agent skill from aaronontheweb/dotnet-skills that teaches robust integration testing for .NET Aspire distributed applications using xUnit. It centers on DistributedApplicationTestingBuilder from the Aspire.Hosting.Testing NuGet package, which launches the full AppHost with real infrastructure (SQL Server, Redis, message queues) in containers instead of mocks. Six core principles cover real dependencies, dynamic port binding (127.0.0.1:0), IAsyncLifetime fixture lifecycle, runtime endpoint discovery, xUnit collection parallelization, and health-check waits via ResourceNotifications. Advanced patterns include Playwright UI tests, Respawn database resets, conditional resource configuration, and CI/CD integration. Developers reach for this skill when testing microservice communication, ASP.NET Core apps with real databases, or Aspire-orchestrated multi-service deployments before release.

  • Aspire test host setup
  • Real dependency wiring
  • Service graph assertions
  • CI-friendly integration runs
  • Regression detection

Aspire Integration Testing by the numbers

  • 376 all-time installs (skills.sh)
  • Ranked #662 of 2,153 Testing & QA skills by installs in the Skillselion catalog
  • Data as of Aug 3, 2026 (Skillselion catalog sync)
npx skills add https://github.com/aaronontheweb/dotnet-skills --skill aspire-integration-testing

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs376
repo stars1.1k
Last updatedJuly 3, 2026
Repositoryaaronontheweb/dotnet-skills

How do you integration test .NET Aspire apps?

Write and run Aspire-hosted integration tests that spin real dependencies, assert service wiring, and catch regressions before release.

Who is it for?

.NET developers writing closed-box integration tests for Aspire distributed applications with real SQL Server, Redis, or message-queue dependencies in containers.

Skip if: Single-project ASP.NET Core apps better served by WebApplicationFactory in-memory tests without full AppHost orchestration.

When should I use this skill?

User asks to integration test .NET Aspire apps, set up DistributedApplicationTestingBuilder fixtures, or test microservices with real containerized dependencies.

What you get

xUnit test fixtures, DistributedApplication test hosts, HttpClient helpers, and CI-ready Aspire integration test suites.

  • xUnit integration test suites
  • IAsyncLifetime test fixtures
  • CI pipeline test configuration

By the numbers

  • Six core testing principles: real deps, dynamic ports, fixtures, discovery, isolation, health
  • Uses Aspire.Hosting.Testing NuGet package with DistributedApplicationTestingBuilder

Files

SKILL.mdMarkdownGitHub ↗

Integration Testing with .NET Aspire + xUnit

When to Use This Skill

Use this skill when:

  • Writing integration tests for .NET Aspire applications
  • Testing ASP.NET Core apps with real database connections
  • Verifying service-to-service communication in distributed applications
  • Testing with actual infrastructure (SQL Server, Redis, message queues) in containers
  • Combining Playwright UI tests with Aspire-orchestrated services
  • Testing microservices with proper service discovery and networking

Reference Files

  • advanced-patterns.md: Endpoint discovery, database testing, Playwright, conditional config, Respawn, service communication, message queues
  • ci-and-tooling.md: CI/CD integration, custom resource waiters, Aspire CLI with MCP

Core Principles

1. Real Dependencies - Use actual infrastructure (databases, caches) via Aspire, not mocks 2. Dynamic Port Binding - Let Aspire assign ports dynamically (127.0.0.1:0) to avoid conflicts 3. Fixture Lifecycle - Use IAsyncLifetime for proper test fixture setup and teardown 4. Endpoint Discovery - Never hard-code URLs; discover endpoints from Aspire at runtime 5. Parallel Isolation - Use xUnit collections to control test parallelization 6. Health Checks - Always wait for services to be healthy before running tests

High-Level Testing Architecture

┌─────────────────┐                    ┌──────────────────────┐
│ xUnit test file │──uses────────────►│  AspireFixture       │
└─────────────────┘                    │  (IAsyncLifetime)    │
                                       └──────────────────────┘
                                               │
                                               │ starts
                                               ▼
                                    ┌───────────────────────────┐
                                    │  DistributedApplication   │
                                    │  (from AppHost)           │
                                    └───────────────────────────┘
                                               │ exposes
                                               ▼
                                  ┌──────────────────────────────┐
                                  │   Dynamic HTTP Endpoints     │
                                  └──────────────────────────────┘
                                               │ consumed by
                                               ▼
                                   ┌─────────────────────────┐
                                   │  HttpClient / Playwright│
                                   └─────────────────────────┘

Required NuGet Packages

<ItemGroup>
  <PackageReference Include="Aspire.Hosting.Testing" Version="$(AspireVersion)" />
  <PackageReference Include="xunit" Version="*" />
  <PackageReference Include="xunit.runner.visualstudio" Version="*" />
  <PackageReference Include="Microsoft.NET.Test.Sdk" Version="*" />
</ItemGroup>

CRITICAL: File Watcher Fix for Integration Tests

When running many integration tests that each start an IHost, the default .NET host builder enables file watchers for configuration reload. This exhausts file descriptor limits on Linux.

Add this to your test project before any tests run:

// TestEnvironmentInitializer.cs
using System.Runtime.CompilerServices;

namespace YourApp.Tests;

internal static class TestEnvironmentInitializer
{
    [ModuleInitializer]
    internal static void Initialize()
    {
        // Disable config file watching in test hosts
        // Prevents file descriptor exhaustion (inotify watch limit) on Linux
        Environment.SetEnvironmentVariable("DOTNET_HOSTBUILDER__RELOADCONFIGONCHANGE", "false");
    }
}

Pattern 1: Basic Aspire Test Fixture (Modern API)

using Aspire.Hosting;
using Aspire.Hosting.Testing;

public sealed class AspireAppFixture : IAsyncLifetime
{
    private DistributedApplication? _app;

    public DistributedApplication App => _app
        ?? throw new InvalidOperationException("App not initialized");

    public async Task InitializeAsync()
    {
        var builder = await DistributedApplicationTestingBuilder
            .CreateAsync<Projects.YourApp_AppHost>([
                "YourApp:UseVolumes=false",
                "YourApp:Environment=IntegrationTest",
                "YourApp:Replicas=1"
            ]);

        _app = await builder.BuildAsync();

        using var startupCts = new CancellationTokenSource(TimeSpan.FromMinutes(10));
        await _app.StartAsync(startupCts.Token);

        using var healthCts = new CancellationTokenSource(TimeSpan.FromMinutes(5));
        await _app.ResourceNotifications.WaitForResourceHealthyAsync("api", healthCts.Token);
    }

    public Uri GetEndpoint(string resourceName, string scheme = "https")
    {
        return _app?.GetEndpoint(resourceName, scheme)
            ?? throw new InvalidOperationException($"Endpoint for '{resourceName}' not found");
    }

    public async Task DisposeAsync()
    {
        if (_app is not null)
        {
            await _app.DisposeAsync();
        }
    }
}

Pattern 2: Using the Fixture in Tests

[CollectionDefinition("Aspire collection")]
public class AspireCollection : ICollectionFixture<AspireAppFixture> { }

[Collection("Aspire collection")]
public class IntegrationTests
{
    private readonly AspireAppFixture _fixture;

    public IntegrationTests(AspireAppFixture fixture)
    {
        _fixture = fixture;
    }

    [Fact]
    public async Task Application_ShouldStart()
    {
        var httpClient = _fixture.App.CreateHttpClient("yourapp");
        var response = await httpClient.GetAsync("/");
        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
    }
}

See advanced-patterns.md for Endpoint Discovery, Database Testing, Playwright UI Tests, Conditional Resource Configuration, Respawn database reset, Service-to-Service Communication, and Message Queue testing patterns.

Common Patterns Summary

PatternUse Case
Basic FixtureSimple HTTP endpoint testing
Endpoint DiscoveryAvoid hard-coded URLs
Database TestingVerify data access layer
Playwright IntegrationFull UI testing with real backend
Configuration OverrideTest-specific settings
Health ChecksEnsure services are ready
Service CommunicationTest distributed system interactions
Message Queue TestingVerify async messaging

Tricky / Non-Obvious Tips

ProblemSolution
Tests timeout immediatelyCall await _app.StartAsync() and wait for services to be healthy
Port conflicts between testsUse xUnit CollectionDefinition to share fixtures
Flaky tests due to timingImplement proper health check polling instead of Task.Delay()
Can't connect to SQL ServerRetrieve connection string dynamically via GetConnectionStringAsync()
Parallel tests interfereUse [Collection] attribute to run related tests sequentially
Aspire dashboard conflictsOnly one dashboard can run at a time; tests reuse the same instance

Best Practices

1. Use `IAsyncLifetime` - Ensures proper async initialization and cleanup 2. Share fixtures via collections - Reduces test execution time by reusing app instances 3. Discover endpoints dynamically - Never hard-code localhost:5000 or similar 4. Wait for health checks - Don't assume services are immediately ready 5. Test with real dependencies - Aspire makes it easy to use real SQL, Redis, etc. 6. Clean up resources - Always implement DisposeAsync properly 7. Use meaningful test data - Seed databases with realistic test data 8. Test failure scenarios - Verify error handling and resilience 9. Keep tests isolated - Each test should be independent and order-agnostic 10. Monitor test execution time - If tests are slow, consider parallelization

See ci-and-tooling.md for GitHub Actions setup, custom resource waiters, and Aspire CLI/MCP integration.

---

Debugging Tips

1. Run Aspire Dashboard - When tests fail, check the dashboard at http://localhost:15888 2. Use Aspire CLI with MCP - Let AI assistants query real application state 3. Enable detailed logging - Set ASPIRE_ALLOW_UNSECURED_TRANSPORT=true for more verbose output 4. Check container logs - Use docker logs to inspect container output 5. Use breakpoints in fixtures - Debug fixture initialization to catch startup issues 6. Verify resource names - Ensure resource names match between AppHost and tests

Related skills

How it compares

Pick aspire-integration-testing for full Aspire AppHost closed-box tests; use WebApplicationFactory when testing a single ASP.NET Core project in isolation without distributed orchestration.

FAQ

What package powers Aspire integration tests?

aspire-integration-testing uses DistributedApplicationTestingBuilder from the Aspire.Hosting.Testing NuGet package to launch the full AppHost with real containerized dependencies for closed-box xUnit integration tests.

Should Aspire tests mock external dependencies?

aspire-integration-testing recommends real infrastructure via Aspire orchestration—SQL Server, Redis, and message queues in containers—rather than mocks, surfacing realistic networking and persistence issues before release.

Testing & QAtestingbackendintegrations

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.