Testes de Integração com Aspire

Escreva testes de integração para aplicações .NET Aspire usando xUnit.

O que é Testes de Integração com Aspire?

Esta habilidade ensina como escrever testes de integração para aplicações .NET Aspire, utilizando xUnit como framework de testes. O foco é testar com dependências reais (bancos de dados, caches, filas) rodando em contêineres, em vez de usar mocks. A arquitetura se baseia em uma fixture compartilhada que inicia a `DistributedApplication` do AppHost, descobre dinamicamente as portas e endpoints HTTP, e garante que os serviços estejam saudáveis antes dos testes. A habilidade cobre desde a configuração básica de projeto (pacotes NuGet, correção do File Watcher para Linux) até padrões avançados como teste de banco de dados, testes de UI com Playwright, comunicação entre serviços e filas de mensagens. Também inclui dicas para depuração, integração com CI/CD e uso da CLI do Aspire com MCP.

Funciona com~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Aaronontheweb/dotnet-skills/tree/main/skills/aspire-integration-testing

Installed? Explore more Programação e Desenvolvimento skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Testes de Integração com .NET Aspire + xUnit

Quando Usar Esta Habilidade

Use esta habilidade quando:

  • Escrevendo testes de integração para aplicações .NET Aspire
  • Testando aplicativos ASP.NET Core com conexões reais a bancos de dados
  • Verificando comunicação serviço a serviço em aplicações distribuídas
  • Testando com infraestrutura real (SQL Server, Redis, filas de mensagens) em contêineres
  • Combinando testes de UI com Playwright e serviços orquestrados pelo Aspire
  • Testando microsserviços com descoberta de serviços e rede adequadas

Arquivos de Referência

  • advanced-patterns.md: Descoberta de endpoints, testes de banco de dados, Playwright, configuração condicional, Respawn, comunicação entre serviços, filas de mensagens
  • ci-and-tooling.md: Integração com CI/CD, espera personalizada por recursos, CLI do Aspire com MCP

Princípios Fundamentais

  1. Dependências Reais - Use infraestrutura real (bancos de dados, caches) via Aspire, não mocks
  2. Bind de Porta Dinâmico - Deixe o Aspire atribuir portas dinamicamente (127.0.0.1:0) para evitar conflitos
  3. Ciclo de Vida da Fixture - Use IAsyncLifetime para setup e teardown adequados da fixture de teste
  4. Descoberta de Endpoints - Nunca hard-code URLs; descubra endpoints do Aspire em tempo de execução
  5. Isolamento Paralelo - Use coleções xUnit para controlar a paralelização dos testes
  6. Health Checks - Sempre aguarde os serviços ficarem saudáveis antes de executar os testes

Arquitetura de Alto Nível dos Testes

┌─────────────────┐                    ┌──────────────────────┐
│ Arquivo de teste │──usa────────────►│  AspireFixture       │
│ xUnit            │                    │  (IAsyncLifetime)    │
└─────────────────┘                    └──────────────────────┘
                                               │
                                               │ inicia
                                               ▼
                                    ┌───────────────────────────┐
                                    │  DistributedApplication   │
                                    │  (do AppHost)             │
                                    └───────────────────────────┘
                                               │ expõe
                                               ▼
                                  ┌──────────────────────────────┐
                                  │   Endpoints HTTP Dinâmicos    │
                                  └──────────────────────────────┘
                                               │ consumidos por
                                               ▼
                                   ┌─────────────────────────┐
                                   │  HttpClient / Playwright│
                                   └─────────────────────────┘

Pacotes NuGet Necessários

<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>

CRÍTICO: Correção do File Watcher para Testes de Integração

Ao executar muitos testes de integração, cada um iniciando um IHost, o builder padrão do .NET habilita file watchers para recarregamento de configuração. Isso esgota os limites de descritores de arquivo no Linux.

Adicione isto ao seu projeto de teste antes de qualquer teste ser executado:

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

namespace SeuApp.Tests;

internal static class TestEnvironmentInitializer
{
    [ModuleInitializer]
    internal static void Initialize()
    {
        // Desabilita o monitoramento de arquivos de configuração nos hosts de teste
        // Previne a exaustão de descritores de arquivo (limite de watches inotify) no Linux
        Environment.SetEnvironmentVariable("DOTNET_HOSTBUILDER__RELOADCONFIGONCHANGE", "false");
    }
}

Padrão 1: Fixture Básica para Teste Aspire (API Moderna)

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

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

    public DistributedApplication App => _app
        ?? throw new InvalidOperationException("App não inicializado");

    public async Task InitializeAsync()
    {
        var builder = await DistributedApplicationTestingBuilder
            .CreateAsync<Projects.SeuApp_AppHost>([
                "SeuApp:UseVolumes=false",
                "SeuApp:Environment=IntegrationTest",
                "SeuApp: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 para '{resourceName}' não encontrado");
    }

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

Padrão 2: Usando a Fixture nos Testes

[CollectionDefinition("Coleção Aspire")]
public class AspireCollection : ICollectionFixture<AspireAppFixture> { }

[Collection("Coleção Aspire")]
public class IntegrationTests
{
    private readonly AspireAppFixture _fixture;

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

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

Veja advanced-patterns.md para padrões de Descoberta de Endpoints, Testes de Banco de Dados, Testes de UI com Playwright, Configuração Condicional de Recursos, Reset de Banco de Dados com Respawn, Comunicação Serviço-a-Serviço e Testes de Filas de Mensagens.

Resumo de Padrões Comuns

PadrãoCaso de Uso
Fixture BásicaTeste simples de endpoints HTTP
Descoberta de EndpointsEvitar URLs hard-coded
Testes de Banco de DadosVerificar camada de acesso a dados
Integração com PlaywrightTeste completo de UI com backend real
Sobrescrita de ConfiguraçãoConfigurações específicas de teste
Health ChecksGarantir que os serviços estão prontos
Comunicação entre ServiçosTestar interações em sistemas distribuídos
Testes de Filas de MensagensVerificar mensageria assíncrona

Dicas Difíceis / Não-Óbvias

ProblemaSolução
Testes expiram imediatamenteChame await _app.StartAsync() e aguarde os serviços ficarem saudáveis
Conflitos de porta entre testesUse CollectionDefinition do xUnit para compartilhar fixtures
Testes instáveis devido ao tempoImplemente polling adequado de health checks em vez de Task.Delay()
Não consigo conectar ao SQL ServerRecupere a string de conexão dinamicamente via GetConnectionStringAsync()
Testes paralelos interferemUse o atributo [Collection] para executar testes relacionados sequencialmente
Conflitos de dashboard do AspireApenas um dashboard pode ser executado por vez; os testes reutilizam a mesma instância

Melhores Práticas

  1. Use IAsyncLifetime - Garante inicialização e limpeza assíncronas adequadas
  2. Compartilhe fixtures via coleções - Reduz o tempo de execução dos testes reutilizando instâncias de aplicação
  3. Descubra endpoints dinamicamente - Nunca hard-code localhost:5000 ou similar
  4. Aguarde health checks - Não presuma que os serviços estão imediatamente prontos
  5. Teste com dependências reais - O Aspire facilita o uso de SQL, Redis, etc. reais
  6. Limpe os recursos - Sempre implemente DisposeAsync corretamente
  7. Use dados de teste significativos - Popule bancos de dados com dados de teste realistas
  8. Teste cenários de falha - Verifique tratamento de erros e resiliência
  9. Mantenha os testes isolados - Cada teste deve ser independente e independente de ordem
  10. Monitore o tempo de execução dos testes - Se os testes forem lentos, considere paralelização

Veja ci-and-tooling.md para configuração do GitHub Actions, espera personalizada por recursos e integração com Aspire CLI/MCP.


Dicas de Depuração

  1. Execute o Dashboard do Aspire - Quando os testes falharem, verifique o dashboard em http://localhost:15888
  2. Use a CLI do Aspire com MCP - Permite que assistentes de IA consultem o estado real da aplicação
  3. Habilite logging detalhado - Defina ASPIRE_ALLOW_UNSECURED_TRANSPORT=true para saída mais verbosa
  4. Verifique logs dos contêineres - Use docker logs para inspecionar a saída dos contêineres
  5. Use breakpoints nas fixtures - Depure a inicialização da fixture para capturar problemas de startup
  6. Verifique nomes dos recursos - Garanta que os nomes dos recursos coincidam entre o AppHost e os testes

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

akka-hosting-actor-patterns

Patterns for building entity actors with Akka.Hosting - GenericChildPerEntityParent, message extractors, cluster sharding abstraction, akka-reminders, and ITimeProvider. Supports both local testing and clustered production modes.

akka-net-aspire-configuration

Configure Akka.NET with .NET Aspire for local development and production deployments. Covers actor system setup, clustering, persistence, Akka.Management integration, and Aspire orchestration patterns.

akka-net-best-practices

Critical Akka.NET best practices including EventStream vs DistributedPubSub, supervision strategies, error handling, Props vs DependencyResolver, work distribution patterns, and cluster/local mode abstractions for testability.

akka-net-management

Akka.Management for cluster bootstrapping, service discovery (Kubernetes, Azure, Config), health checks, and dynamic cluster formation without static seed nodes.

akka-net-testing-patterns

Write unit and integration tests for Akka.NET actors using modern Akka.Hosting.TestKit patterns. Covers dependency injection, TestProbes, persistence testing, and actor interaction verification. Includes guidance on when to use traditional TestKit.

api-design

Design stable, compatible public APIs using extend-only design principles. Manage API compatibility, wire compatibility, and versioning for NuGet packages and distributed systems.

aspire-configuration

Configure Aspire AppHost to emit explicit app config via environment variables; keep app code free of Aspire clients and service discovery.

aspire-service-defaults

Create a shared ServiceDefaults project for Aspire applications. Centralizes OpenTelemetry, health checks, resilience, and service discovery configuration across all services.

crap-analysis

Analyze code coverage and CRAP (Change Risk Anti-Patterns) scores to identify high-risk code. Use OpenCover format with ReportGenerator for Risk Hotspots showing cyclomatic complexity and untested code paths.

csharp-concurrency-patterns

Choosing the right concurrency abstraction in .NET - from async/await for I/O to Channels for producer/consumer to Akka.NET for stateful entity management. Avoid locks and manual synchronization unless absolutely necessary.

database-performance

Database access patterns for performance. Separate read/write models, avoid N+1 queries, use AsNoTracking, apply row limits, and never do application-side joins. Works with EF Core and Dapper.

dependency-injection-patterns

Organize DI registrations using IServiceCollection extension methods. Group related services into composable Add* methods for clean Program.cs and reusable configuration in tests.

dotnet-devcert-trust

Diagnose and fix .NET HTTPS dev certificate trust issues on Linux. Covers the full certificate lifecycle from generation to system CA bundle inclusion, with distro-specific guidance for Ubuntu, Fedora, Arch, and WSL2.

dotnet-local-tools

Managing local .NET tools with dotnet-tools.json for consistent tooling across development environments and CI/CD pipelines.

dotnet-project-structure

Modern .NET project structure including .slnx solution format, Directory.Build.props, central package management, SourceLink, version management with RELEASE_NOTES.md, and SDK pinning with global.json.

dotnet-slopwatch

Use Slopwatch to detect LLM reward hacking in .NET code changes. Run after every code modification to catch disabled tests, suppressed warnings, empty catch blocks, and other shortcuts that mask real problems.

efcore-patterns

Entity Framework Core best practices including NoTracking by default, query splitting for navigation collections, migration management, dedicated migration services, and common pitfalls to avoid.

ilspy-decompile

Understand implementation details of .NET code by decompiling assemblies. Use when you want to see how a .NET API works internally, inspect NuGet package source, view framework implementation, or understand compiled .NET binaries.

mailpit-integration

Test email sending locally using Mailpit with .NET Aspire. Captures all outgoing emails without sending them. View rendered HTML, inspect headers, and verify delivery in integration tests.

marketplace-publishing

Workflow for publishing skills and agents to the dotnet-skills Claude Code marketplace. Covers adding new content, updating plugin.json, validation, and release tagging.

Habilidades Relacionadas