Skip to content
Shiny.NET

Testing

Terminal window
dotnet add package Shiny.Actors.Testing

ActorTestHost 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