dapr / dotnet-sdk

Dapr SDK for .NET

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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.