Testing
dotnet add package Shiny.Actors.TestingActorTestHost is a whole actor system in one line, with fake time and in-memory storage. It works with any test
framework.
await using var host = new ActorTestHost(services => services.AddSingleton<IClock, FakeClock>());
await host.SetStateAsync<CartActor, CartState>(new CartState { Items = ["coffee"] }, id: "allan");await host.Get<ICart>("allan").Checkout();await host.AdvanceAsync(TimeSpan.FromHours(1)); // timers, reminders, idle deactivation - no sleeps
Assert.Single(host.Calls, c => c.Method == "Checkout" && !c.Failed);Assert.Equal([new Deposited(10m)], await host.GetEventsAsync<AccountActor, AccountEvent>("a"));using var orders = host.Record<OrderPlaced>("store-1"); // .Items, await .WaitForAsync(n)The constructor takes an optional service registration callback, an optional ShinyActorBuilder callback (to add
filters, migrations or durable streams), and an optional start time.
| Member | |
|---|---|
Get<T>(id) / GetStream<T>(key) |
The same as on IActorSystem. id defaults to "test" |
Time |
The FakeTimeProvider, shared through DI as TimeProvider |
AdvanceAsync(by) |
Moves time forward, firing timers and reminders and deactivating idle actors along the way |
WaitForQuietAsync() |
Waits until nothing is queued, running, or mid-reminder anywhere in the system |
FireDueRemindersAsync() |
Fires whatever is due now |
DeactivateAllAsync() |
Deactivates every actor, for example to test that state survives |
Calls |
Every call made, as RecordedCall (actor, id, method, arguments, result, exception, Failed) |
Record<T>(key) |
A StreamRecorder<T> with Items and WaitForAsync(count) |
SetStateAsync / GetStateAsync |
Seed and inspect an actor’s stored state, including named states |
GetEventsAsync<TActor, TEvent>(id) |
A journaled actor’s confirmed events |
GetRemindersAsync<TActor>(id) |
An actor’s registered reminders |
StateStore / ReminderStore / EventStore |
The in-memory stores behind it all |


