Padrões de Teste para Akka.NET

Escreva testes unitários e de integração para atores Akka.NET usando os padrões modernos do Akka.Hosting.TestKit. Abrange injeção de dependência, TestProbes, teste de persistência e verificação de interação entre atores. Inclui orientação sobre quando usar o TestKit tradicional.

O que é Padrões de Teste para Akka.NET?

Esta habilidade fornece um guia completo e prático para escrever testes unitários e de integção para aplicações Akka.NET utilizando o framework moderno Akka.Hosting.TestKit, recomendado para 95% dos casos de uso. O principal diferencial é a integração nativa com o sistema de injeção de dependência do .NET (Microsoft.Extensions.DependencyInjection), permitindo substituir serviços reais por fakes ou mocks diretamente nos testes, sem a necessidade de configurações complexas. A habilidade cobre desde o padrão mais básico de teste de um único ator até cenários avançados como teste de atores persistentes (com event sourcing e recuperação de estado), sharding de cluster em modo local, e testes de integração baseados em cenários completos de negócio. Inclui também uma correção crítica para evitar o esgotamento de descritores de arquivo (inotify) no Linux ao executar muitos testes, uma solução essencial para ambientes CI/CD. As plataformas suportadas são projetos .NET modernos que utilizam Akka.NET v1.5+, ASP.NET Core, Worker Services e .NET Aspire. A abordagem proposta se baseia em herdar da classe base `TestKit`, sobrescrever os métodos `ConfigureServices()` e `ConfigureAkka()`, e utilizar o `ActorRegistry` para acesso tip-safe a referências de atores.

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

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

O que Padrões de Teste para Akka.NET faz?

Quando Usar Esta Habilidade

Use esta habilidade quando:

  • Escrever testes unitários para atores Akka.NET
  • Testar atores persistentes com event sourcing
  • Verificar interações entre atores e fluxos de mensagens
  • Testar supervisão e ciclo de vida de atores
  • Simular dependências externas em testes de atores
  • Testar comportamento de cluster sharding localmente
  • Verificar recuperação de estado e persistência de atores

Arquivos de Referência

Escolhendo sua Abordagem de Teste

Use Akka.Hosting.TestKit (Recomendado para 95% dos Casos)

Quando:

  • Construir aplicações .NET modernas com Microsoft.Extensions.DependencyInjection
  • Usar Akka.Hosting para configuração de atores em produção
  • Precisar injetar serviços em atores (IOptions, DbContext, ILogger, clientes HTTP, etc.)
  • Testar aplicações que usam ASP.NET Core, Worker Services ou .NET Aspire
  • Trabalhar com projetos Akka.NET modernos (Akka.NET v1.5+)

Vantagens:

  • Suporte nativo a injeção de dependência - substitua serviços por fakes nos testes
  • Paridade de configuração com produção (os mesmos métodos de extensão funcionam nos testes)
  • Separação limpa entre lógica do ator e infraestrutura
  • Registro de atores tip-safe para recuperação de atores

Use Akka.TestKit Tradicional

Quando:

  • Contribuir para o desenvolvimento da biblioteca principal do Akka.NET
  • Trabalhar em ambientes sem Microsoft.Extensions (aplicações console, sistemas legados)
  • Bases de código legadas que usam criação manual de Props sem DI

Consulte anti-patterns-and-reference.md para padrões do TestKit tradicional.


Princípios Fundamentais (Akka.Hosting.TestKit)

  1. Herdar de Akka.Hosting.TestKit.TestKit - Esta é uma classe base do framework, não uma classe definida pelo usuário
  2. Sobrescrever ConfigureServices() - Substitua serviços reais por fakes/mocks
  3. Sobrescrever ConfigureAkka() - Configure atores usando os mesmos métodos de extensão da produção
  4. Usar ActorRegistry - Recuperação tip-safe de referências de atores
  5. Composição sobre Herança - Serviços fake como campos, não classes base
  6. Sem Classes Base Personalizadas - Use sobrescritas de métodos, não hierarquias de herança
  7. Teste um Ator por Vez - Use TestProbes para dependências
  8. Corresponder aos Padrões de Produção - Mesmos métodos de extensão, AkkaExecutionMode diferente

Pacotes NuGet Necessários

<ItemGroup>
  <!-- Framework de teste principal -->
  <PackageReference Include="Akka.Hosting.TestKit" Version="*" />

  <!-- xUnit (ou seu framework de teste preferido) -->
  <PackageReference Include="xunit" Version="*" />
  <PackageReference Include="xunit.runner.visualstudio" Version="*" />
  <PackageReference Include="Microsoft.NET.Test.Sdk" Version="*" />

  <!-- Asserções (recomendado) -->
  <PackageReference Include="FluentAssertions" Version="*" />

  <!-- Persistência em memória para testes -->
  <PackageReference Include="Akka.Persistence.Hosting" Version="*" />

  <!-- Se testar cluster sharding -->
  <PackageReference Include="Akka.Cluster.Hosting" Version="*" />
</ItemGroup>

CRÍTICO: Correção do File Watcher para Projetos de Teste

O Akka.Hosting.TestKit cria instâncias reais de IHost, que por padrão habilitam observadores de arquivo para recarga de configuração. Ao executar muitos testes, isso esgota os limites de descritores de arquivo no Linux (limite de observação inotify).

Adicione isso ao seu projeto de teste - ele é executado antes de qualquer teste:

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

namespace YourApp.Tests;

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

Por que isso é importante:

  • [ModuleInitializer] é executado automaticamente antes de qualquer código de teste
  • Define a variável de ambiente globalmente para todas as instâncias de IHost
  • Previne erros obscuros de inotify ao executar 100+ testes
  • Também se aplica a testes de integração com Aspire que usam IHost

Visão Geral dos Padrões de Teste

Cada padrão abaixo tem uma descrição resumida. Consulte examples.md para exemplos de código completos.

Padrão 1: Teste Básico de Ator

O padrão fundamental. Sobrescreva ConfigureServices() para injetar fakes, sobrescreva ConfigureAkka() para registrar atores com os mesmos métodos de extensão da produção.

public class OrderActorTests : TestKit
{
    private readonly FakeOrderRepository _fakeRepository = new();

    protected override void ConfigureServices(HostBuilderContext context, IServiceCollection services)
    {
        services.AddSingleton<IOrderRepository>(_fakeRepository);
    }

    protected override void ConfigureAkka(AkkaConfigurationBuilder builder, IServiceProvider provider)
    {
        builder.WithInMemoryJournal().WithInMemorySnapshotStore();
        builder.WithActors((system, registry, resolver) =>
        {
            registry.Register<OrderActor>(system.ActorOf(resolver.Props<OrderActor>(), "order-actor"));
        });
    }

    [Fact]
    public async Task CreateOrder_Success_SavesToRepository()
    {
        var orderActor = ActorRegistry.Get<OrderActor>();
        var response = await orderActor.Ask<OrderCommandResult>(
            new CreateOrder("ORDER-123", "CUST-456", 99.99m), RemainingOrDefault);
        response.Status.Should().Be(CommandStatus.Success);
        _fakeRepository.SaveCallCount.Should().Be(1);
    }
}

Padrão 2: TestProbe para Interações entre Atores

Registre um TestProbe no ActorRegistry como substituto para um ator de dependência. Use ExpectMsgAsync<T>() para verificar se as mensagens foram enviadas.

Padrão 3: TestProbe com Resposta Automática

Quando o ator sob teste usa Ask para se comunicar com dependências, crie um ator de resposta automática que encaminha mensagens para uma sonda E responde para evitar timeouts.

Padrão 4: Teste de Atores Persistentes

Use WithInMemoryJournal() e WithInMemorySnapshotStore(). Teste a recuperação matando o ator com PoisonPill e consultando para forçar a recuperação do journal.

Padrão 5: Reutilizar Configuração de Produção

Sempre reutilize os métodos de extensão da produção nos testes em vez de duplicar a configuração HOCON. Isso garante que os testes usem exatamente a mesma configuração da produção.

protected override void ConfigureAkka(AkkaConfigurationBuilder builder, IServiceProvider provider)
{
    builder
        .AddDraftSerializer()                                    // Mesmo da produção
        .AddOrderDomainActors(AkkaExecutionMode.LocalTest)      // Mesmo, mas modo local
        .WithInMemoryJournal().WithInMemorySnapshotStore();      // Substituições específicas de teste
}

Padrão 6: Cluster Sharding Localmente

Use AkkaExecutionMode.LocalTest com GenericChildPerEntityParent para testar o comportamento de sharding sem um cluster real. Mesmos métodos de extensão, modo diferente.

Padrão 7: AwaitAssertAsync para Operações Assíncronas

Use AwaitAssertAsync quando atores realizam operações assíncronas. Ele tenta novamente as asserções até que passem ou atinjam o timeout, prevenindo testes instáveis.

await AwaitAssertAsync(() =>
{
    _fakeReadModelService.SyncCallCount.Should().BeGreaterOrEqualTo(1);
}, TimeSpan.FromSeconds(3));

Padrão 8: Testes de Integração Baseados em Cenários

Teste fluxos de trabalho de negócio completos de ponta a ponta com múltiplos atores e transições de estado. Registre todos os atores do domínio, verifique o estado em cada etapa.


Resumo dos Padrões Comuns

PadrãoCaso de Uso
Teste Básico de AtorAtor único com serviços injetados
TestProbeVerificar se o ator envia mensagens para dependências
Respondedor AutomáticoEvitar timeouts de Ask durante testes
Ator PersistenteTestar event sourcing e recuperação
Cluster ShardingTestar comportamento de sharding localmente
AwaitAssertAsyncLidar com operações assíncronas em atores
Testes de CenárioFluxos de trabalho de negócio completos

Melhores Práticas

  1. Uma classe de teste por ator - Mantenha os testes focados
  2. Sobrescreva ConfigureServices/ConfigureAkka - Não crie classes base
  3. Use fakes, não mocks - Mais simples, mais fáceis de manter
  4. Teste um ator por vez - Use TestProbes para dependências
  5. Corresponda aos padrões de produção - Mesmos métodos de extensão, AkkaExecutionMode diferente
  6. Use AwaitAssertAsync para operações assíncronas - Previne testes instáveis
  7. Teste a recuperação - Mate e reinicie atores para verificar persistência
  8. Testes de cenário para fluxos de trabalho - Teste fluxos completos de negócio ponta a ponta
  9. Mantenha os testes rápidos - Persistência em memória, sem bancos de dados reais
  10. Use nomes significativos - Scenario_FirstTimePurchase_SuccessfulPayment

Dicas de Depuração

  1. Ative logging de depuração - Passe LogLevel.Debug para o construtor do TestKit
  2. Use ITestOutputHelper - Veja logs do sistema de atores na saída do teste
  3. Inspecione o TestProbe - Verifique probe.Messages para ver o que foi enviado
  4. Consulte o estado do ator - Adicione mensagens de consulta de estado para depuração
  5. Use AwaitAssertAsync com logging - Veja por que as asserções falham
  6. Verifique o ActorRegistry - Confirme se os atores estão registrados corretamente
// Construtor com logging de depuração
public OrderActorTests(ITestOutputHelper output)
    : base(output: output, logLevel: LogLevel.Debug)
{
}

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.

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

Write integration tests using .NET Aspire

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