Documentation on writing unit tests for Actors that access state
jaq316 opened this issue · comments
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.