dotnet-sdk
dotnet-sdk copied to clipboard
Documentation on writing unit tests for Actors that access state
Documentation on writing unit tests, specifically for Actors accessing state would be great.
The below code, for instance, would throw: "InvalidOperationException: The actor was initialized without a state provider, and so cannot interact with state. If this is inside a unit test, replace Actor.StateProvider with a mock."
internal class MyActor : Actor, IMyActor
{
private const string STATE_KEY = "counter";
public MyActor(ActorHost host) // Accept ActorHost in the constructor
: base(host) // Pass ActorHost to the base class constructor
{
}
public async Task<int> GetCounter()
{
var iCounterState =(await StateManager.TryGetStateAsync<int>(STATE_KEY).ConfigureAwait(false));
return iCounterState.Value;
}
public async Task Increment()
{
var iCounterState = (await StateManager.TryGetStateAsync<int>(STATE_KEY).ConfigureAwait(false));
if (iCounterState.HasValue)
{
await StateManager.SetStateAsync(STATE_KEY, iCounterState.Value + 1).ConfigureAwait(false);
}
else
{
await StateManager.SetStateAsync(STATE_KEY, 1).ConfigureAwait(false);
}
}
}
public class MyActorTests
{
[Fact]
public async Task SomeMethod_ShouldSucceed()
{
// Arrange
var actorId = new ActorId("test");
var host = ActorHost.CreateForTest<MyActor>(new ActorTestOptions
{
ActorId = actorId
});
var myActor = new MyActor(host);
// Act
await myActor.Increment();
var counter = myActor.GetCounter();
// Assert
Assert.AreEqual(1, counter);
}
}
https://github.com/dapr/dotnet-sdk/blob/3b979e6bdb1d779563f1656fa684183b2bfecd08/test/Dapr.Actors.Test/ITestActor.cs#L47C31-L47C31 implements overriding of the StateManager by providing an optional IStateManager parameter in the constructor. If that is provided, this.StateManager
is set in the constructor.