$npx -y skills add Aaronontheweb/dotnet-skills --skill akka-testing-patternsWrite 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.
| 1 | # Akka.NET Testing Patterns |
| 2 | |
| 3 | ## When to Use This Skill |
| 4 | |
| 5 | Use this skill when: |
| 6 | - Writing unit tests for Akka.NET actors |
| 7 | - Testing persistent actors with event sourcing |
| 8 | - Verifying actor interactions and message flows |
| 9 | - Testing actor supervision and lifecycle |
| 10 | - Mocking external dependencies in actor tests |
| 11 | - Testing cluster sharding behavior locally |
| 12 | - Verifying actor state recovery and persistence |
| 13 | |
| 14 | ## Reference Files |
| 15 | |
| 16 | - [examples.md](examples.md): Complete code samples for all testing patterns (Patterns 1-8 plus Reminders) |
| 17 | - [anti-patterns-and-reference.md](anti-patterns-and-reference.md): Anti-patterns, traditional TestKit, CI/CD integration |
| 18 | |
| 19 | ## Choosing Your Testing Approach |
| 20 | |
| 21 | ### Use Akka.Hosting.TestKit (Recommended for 95% of Use Cases) |
| 22 | |
| 23 | **When:** |
| 24 | - Building modern .NET applications with `Microsoft.Extensions.DependencyInjection` |
| 25 | - Using Akka.Hosting for actor configuration in production |
| 26 | - Need to inject services into actors (`IOptions`, `DbContext`, `ILogger`, HTTP clients, etc.) |
| 27 | - Testing applications that use ASP.NET Core, Worker Services, or .NET Aspire |
| 28 | - Working with modern Akka.NET projects (Akka.NET v1.5+) |
| 29 | |
| 30 | **Advantages:** |
| 31 | - Native dependency injection support - override services with fakes in tests |
| 32 | - Configuration parity with production (same extension methods work in tests) |
| 33 | - Clean separation between actor logic and infrastructure |
| 34 | - Type-safe actor registry for retrieving actors |
| 35 | |
| 36 | ### Use Traditional Akka.TestKit |
| 37 | |
| 38 | **When:** |
| 39 | - Contributing to Akka.NET core library development |
| 40 | - Working in environments without `Microsoft.Extensions` (console apps, legacy systems) |
| 41 | - Legacy codebases using manual `Props` creation without DI |
| 42 | |
| 43 | See [anti-patterns-and-reference.md](anti-patterns-and-reference.md) for traditional TestKit patterns. |
| 44 | |
| 45 | --- |
| 46 | |
| 47 | ## Core Principles (Akka.Hosting.TestKit) |
| 48 | |
| 49 | 1. **Inherit from `Akka.Hosting.TestKit.TestKit`** - This is a framework base class, not a user-defined one |
| 50 | 2. **Override `ConfigureServices()`** - Replace real services with fakes/mocks |
| 51 | 3. **Override `ConfigureAkka()`** - Configure actors using the same extension methods as production |
| 52 | 4. **Use `ActorRegistry`** - Type-safe retrieval of actor references |
| 53 | 5. **Composition over Inheritance** - Fake services as fields, not base classes |
| 54 | 6. **No Custom Base Classes** - Use method overrides, not inheritance hierarchies |
| 55 | 7. **Test One Actor at a Time** - Use TestProbes for dependencies |
| 56 | 8. **Match Production Patterns** - Same extension methods, different `AkkaExecutionMode` |
| 57 | |
| 58 | --- |
| 59 | |
| 60 | ## Required NuGet Packages |
| 61 | |
| 62 | ```xml |
| 63 | <ItemGroup> |
| 64 | <!-- Core testing framework --> |
| 65 | <PackageReference Include="Akka.Hosting.TestKit" Version="*" /> |
| 66 | |
| 67 | <!-- xUnit (or your preferred test framework) --> |
| 68 | <PackageReference Include="xunit" Version="*" /> |
| 69 | <PackageReference Include="xunit.runner.visualstudio" Version="*" /> |
| 70 | <PackageReference Include="Microsoft.NET.Test.Sdk" Version="*" /> |
| 71 | |
| 72 | <!-- Assertions (recommended) --> |
| 73 | <PackageReference Include="FluentAssertions" Version="*" /> |
| 74 | |
| 75 | <!-- In-memory persistence for testing --> |
| 76 | <PackageReference Include="Akka.Persistence.Hosting" Version="*" /> |
| 77 | |
| 78 | <!-- If testing cluster sharding --> |
| 79 | <PackageReference Include="Akka.Cluster.Hosting" Version="*" /> |
| 80 | </ItemGroup> |
| 81 | ``` |
| 82 | |
| 83 | --- |
| 84 | |
| 85 | ## CRITICAL: File Watcher Fix for Test Projects |
| 86 | |
| 87 | 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). |
| 88 | |
| 89 | **Add this to your test project - it runs before any tests execute:** |
| 90 | |
| 91 | ```csharp |
| 92 | // TestEnvironmentInitializer.cs |
| 93 | using System.Runtime.CompilerServices; |
| 94 | |
| 95 | namespace YourApp.Tests; |
| 96 | |
| 97 | internal static class TestEnvironmentInitializer |
| 98 | { |
| 99 | [ModuleInitializer] |
| 100 | internal static void Initialize() |
| 101 | { |
| 102 | // Disable config file watching in test hosts |
| 103 | // Prevents file descriptor exhaustion (inotify watch limit) on Linux |
| 104 | Environment.SetEnvironmentVariable("DOTNET_HOSTBUILDER__RELOADCONFIGONCHANGE", "false"); |
| 105 | } |
| 106 | } |
| 107 | ``` |
| 108 | |
| 109 | **Why this matters:** |
| 110 | - `[ModuleInitializer]` runs automatically before any test code |
| 111 | - Sets the environment variable globally for all `IHost` instances |
| 112 | - Prevents cryptic `inotify` errors when running 100+ tests |
| 113 | - Also applies to Aspire integration tests that use `IHost` |
| 114 | |
| 115 | --- |
| 116 | |
| 117 | ## Testing Patterns Overview |
| 118 | |
| 119 | Each pattern below has a condensed description. See [examples.md](examples.md) for complete code samples. |
| 120 | |
| 121 | ### Pattern 1: Basic Actor Test |
| 122 | |
| 123 | The foundation pattern. Override `ConfigureServices()` to inject fakes, override `ConfigureAkka()` to register actors with the same extension methods as production. |
| 124 | |
| 125 | ```csharp |
| 126 | public class OrderActorTests : |