akka-net-testing-patterns by aaronontheweb/dotnet-skills
npx skills add https://github.com/aaronontheweb/dotnet-skills --skill akka-net-testing-patterns在以下情况下使用此技能:
适用场景:
Microsoft.Extensions.DependencyInjection 构建现代 .NET 应用程序IOptions、DbContext、ILogger、HTTP 客户端等)广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
优势:
适用场景:
Microsoft.Extensions 的环境中工作(控制台应用程序、遗留系统)Props 创建且没有 DI 的遗留代码库传统 TestKit 模式请参阅 anti-patterns-and-reference.md。
Akka.Hosting.TestKit.TestKit - 这是一个框架基类,而非用户定义的类ConfigureServices() - 用伪造/模拟服务替换真实服务ConfigureAkka() - 使用与生产环境相同的扩展方法配置演员ActorRegistry - 类型安全地检索演员引用AkkaExecutionMode<ItemGroup>
<!-- 核心测试框架 -->
<PackageReference Include="Akka.Hosting.TestKit" Version="*" />
<!-- xUnit(或您首选的测试框架) -->
<PackageReference Include="xunit" Version="*" />
<PackageReference Include="xunit.runner.visualstudio" Version="*" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="*" />
<!-- 断言(推荐) -->
<PackageReference Include="FluentAssertions" Version="*" />
<!-- 用于测试的内存持久化 -->
<PackageReference Include="Akka.Persistence.Hosting" Version="*" />
<!-- 如果测试集群分片 -->
<PackageReference Include="Akka.Cluster.Hosting" Version="*" />
</ItemGroup>
Akka.Hosting.TestKit 会启动真实的 IHost 实例,默认情况下会为配置重载启用文件监视器。当运行大量测试时,这会耗尽 Linux 上的文件描述符限制(inotify 监视限制)。
将此添加到您的测试项目中 - 它在任何测试执行之前运行:
// TestEnvironmentInitializer.cs
using System.Runtime.CompilerServices;
namespace YourApp.Tests;
internal static class TestEnvironmentInitializer
{
[ModuleInitializer]
internal static void Initialize()
{
// 在测试主机中禁用配置文件监视
// 防止 Linux 上文件描述符耗尽(inotify 监视限制)
Environment.SetEnvironmentVariable("DOTNET_HOSTBUILDER__RELOADCONFIGONCHANGE", "false");
}
}
为什么这很重要:
[ModuleInitializer] 在任何测试代码之前自动运行IHost 实例全局设置环境变量inotify 错误IHost 的 Aspire 集成测试以下每个模式都有简要描述。完整代码示例请参阅 examples.md。
基础模式。重写 ConfigureServices() 以注入伪造服务,重写 ConfigureAkka() 以使用与生产环境相同的扩展方法注册演员。
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);
}
}
在 ActorRegistry 中注册一个 TestProbe 作为依赖演员的替身。使用 ExpectMsgAsync<T>() 验证消息是否已发送。
当被测试的演员使用 Ask 与依赖项通信时,创建一个自动响应者演员,该演员将消息转发给探针并回复以避免超时。
使用 WithInMemoryJournal() 和 WithInMemorySnapshotStore()。通过使用 PoisonPill 杀死演员并查询以强制从日志恢复来测试恢复。
在测试中始终重用生产扩展方法,而不是复制 HOCON 配置。这确保测试使用与生产环境完全相同的配置。
protected override void ConfigureAkka(AkkaConfigurationBuilder builder, IServiceProvider provider)
{
builder
.AddDraftSerializer() // 与生产环境相同
.AddOrderDomainActors(AkkaExecutionMode.LocalTest) // 相同,但为本地模式
.WithInMemoryJournal().WithInMemorySnapshotStore(); // 测试特定的覆盖
}
使用 AkkaExecutionMode.LocalTest 和 GenericChildPerEntityParent 来测试分片行为,而无需实际集群。相同的扩展方法,不同的模式。
当演员执行异步操作时,使用 AwaitAssertAsync。它会重试断言直到通过或超时,防止测试不稳定。
await AwaitAssertAsync(() =>
{
_fakeReadModelService.SyncCallCount.Should().BeGreaterOrEqualTo(1);
}, TimeSpan.FromSeconds(3));
使用多个演员和状态转换端到端地测试完整的业务工作流。注册所有领域演员,验证每个步骤的状态。
| 模式 | 用例 |
|---|---|
| 基础演员测试 | 具有注入服务的单个演员 |
| TestProbe | 验证演员向依赖项发送消息 |
| 自动响应者 | 测试时避免 Ask 超时 |
| 持久化演员 | 测试事件溯源和恢复 |
| 集群分片 | 本地测试分片行为 |
| AwaitAssertAsync | 处理演员中的异步操作 |
| 场景测试 | 端到端的业务工作流 |
AkkaExecutionModeScenario_FirstTimePurchase_SuccessfulPaymentLogLevel.Debug 传递给 TestKit 构造函数probe.Messages 以了解发送的内容// 带调试日志的构造函数
public OrderActorTests(ITestOutputHelper output)
: base(output: output, logLevel: LogLevel.Debug)
{
}
每周安装次数
86
仓库
GitHub 星标数
495
首次出现
2026 年 1 月 28 日
安全审计
安装于
claude-code68
codex52
opencode51
github-copilot49
gemini-cli49
kimi-cli46
Use this skill when:
When:
Microsoft.Extensions.DependencyInjectionIOptions, DbContext, ILogger, HTTP clients, etc.)Advantages:
When:
Microsoft.Extensions (console apps, legacy systems)Props creation without DISee anti-patterns-and-reference.md for traditional TestKit patterns.
Akka.Hosting.TestKit.TestKit - This is a framework base class, not a user-defined oneConfigureServices() - Replace real services with fakes/mocksConfigureAkka() - Configure actors using the same extension methods as productionActorRegistry - Type-safe retrieval of actor referencesAkkaExecutionMode<ItemGroup>
<!-- Core testing framework -->
<PackageReference Include="Akka.Hosting.TestKit" Version="*" />
<!-- xUnit (or your preferred test framework) -->
<PackageReference Include="xunit" Version="*" />
<PackageReference Include="xunit.runner.visualstudio" Version="*" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="*" />
<!-- Assertions (recommended) -->
<PackageReference Include="FluentAssertions" Version="*" />
<!-- In-memory persistence for testing -->
<PackageReference Include="Akka.Persistence.Hosting" Version="*" />
<!-- If testing cluster sharding -->
<PackageReference Include="Akka.Cluster.Hosting" Version="*" />
</ItemGroup>
Akka.Hosting.TestKit spins up real IHost instances, which by default enable file watchers for configuration reload. When running many tests, this exhausts file descriptor limits on Linux (inotify watch limit).
Add this to your test project - it runs before any tests execute:
// 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");
}
}
Why this matters:
[ModuleInitializer] runs automatically before any test codeIHost instancesinotify errors when running 100+ testsIHostEach pattern below has a condensed description. See examples.md for complete code samples.
The foundation pattern. Override ConfigureServices() to inject fakes, override ConfigureAkka() to register actors with the same extension methods as production.
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);
}
}
Register a TestProbe in the ActorRegistry as a stand-in for a dependency actor. Use ExpectMsgAsync<T>() to verify messages were sent.
When the actor under test uses Ask to communicate with dependencies, create an auto-responder actor that forwards messages to a probe AND replies to avoid timeouts.
Use WithInMemoryJournal() and WithInMemorySnapshotStore(). Test recovery by killing the actor with PoisonPill and querying to force recovery from journal.
Always reuse production extension methods in tests instead of duplicating HOCON config. This ensures tests use the exact same configuration as production.
protected override void ConfigureAkka(AkkaConfigurationBuilder builder, IServiceProvider provider)
{
builder
.AddDraftSerializer() // Same as production
.AddOrderDomainActors(AkkaExecutionMode.LocalTest) // Same, but local mode
.WithInMemoryJournal().WithInMemorySnapshotStore(); // Test-specific overrides
}
Use AkkaExecutionMode.LocalTest with GenericChildPerEntityParent to test sharding behavior without an actual cluster. Same extension methods, different mode.
Use AwaitAssertAsync when actors perform async operations. It retries assertions until they pass or timeout, preventing flaky tests.
await AwaitAssertAsync(() =>
{
_fakeReadModelService.SyncCallCount.Should().BeGreaterOrEqualTo(1);
}, TimeSpan.FromSeconds(3));
Test complete business workflows end-to-end with multiple actors and state transitions. Register all domain actors, verify state at each step.
| Pattern | Use Case |
|---|---|
| Basic Actor Test | Single actor with injected services |
| TestProbe | Verify actor sends messages to dependencies |
| Auto-Responder | Avoid Ask timeouts when testing |
| Persistent Actor | Test event sourcing and recovery |
| Cluster Sharding | Test sharding behavior locally |
| AwaitAssertAsync | Handle async operations in actors |
| Scenario Tests | End-to-end business workflows |
AkkaExecutionModeScenario_FirstTimePurchase_SuccessfulPaymentLogLevel.Debug to TestKit constructorprobe.Messages to see what was sent// Constructor with debug logging
public OrderActorTests(ITestOutputHelper output)
: base(output: output, logLevel: LogLevel.Debug)
{
}
Weekly Installs
86
Repository
GitHub Stars
495
First Seen
Jan 28, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
claude-code68
codex52
opencode51
github-copilot49
gemini-cli49
kimi-cli46
测试策略完整指南:单元/集成/E2E测试金字塔与自动化实践
11,200 周安装
intent-layer 意图层:分层式 AI 智能体代码库导航基础设施 | AGENTS.md 最佳实践
190 周安装
API测试指南:使用Supertest和pytest进行HTTP接口自动化测试
195 周安装
Nansen DCA追踪器:监控Solana鲸鱼美元成本平均法投资策略与聪明资金流向
194 周安装
Claude Code Team技能:AI智能体团队协作,自动化任务分解与执行
194 周安装
Java 21+ 专家技能:虚拟线程、Spring Boot 3.x、JVM优化与云原生开发指南
195 周安装
Symfony 运行器选择:优化架构与工作流,安全执行复杂变更 | Symfony 项目开发工具
195 周安装