dotnet-sdk icon indicating copy to clipboard operation
dotnet-sdk copied to clipboard

Added the ability to supply a state manager for testing purposes.

Open TheRubble opened this issue 3 years ago • 2 comments

While trying to test a custom actor I ran into a situation where it wasn't possible to supply a custom state via the actor test options

ActorHost.CreateForTest<SubmissionChecksActor>(new ActorTestOptions
{
    TimerManager = timerManager.Object,
});

This PR introduces a new interface and allows it to be supplied as per the rest of the items. I've added a test which shows the usage.

public async Task CanSupplyACustomStateStore()
    {
        var stateManager = new Mock<IDaprStateProvider>();
        var host = ActorHost.CreateForTest<CoolTestActor>(new ActorTestOptions(){ DaprStateProvider = stateManager.Object });
        var actor = new CoolTestActor(host);

        await actor.CanTalkToStateManager();

        stateManager.Verify(x => x.ContainsStateAsync(
            "CoolTestActor", 
            actor.Id.GetId(),
            "cool-test-state", CancellationToken.None), Times.Once);
        
    }

I've copied the code style where possible.

Please make sure you've completed the relevant tasks for this PR, out of the following list:

  • [x] Code compiles correctly
  • [x] Created/updated tests
  • [x] Tests run

TheRubble avatar Feb 17 '22 13:02 TheRubble

@TheRubble - Thanks for submitting this! I believe you can already achieve this though. Take a look at the TestActor implementation and how it's used.

https://github.com/dapr/dotnet-sdk/blob/master/test/Dapr.Actors.Test/ITestActor.cs#L47 https://github.com/dapr/dotnet-sdk/blob/master/test/Dapr.Actors.Test/Runtime/ActorTests.cs#L30

halspang avatar Feb 18 '22 01:02 halspang

Hi,

Yes you're correct I can do it that way, I'd totally missed it as I'd focussed on using CreateForTest.

Couple of comments, it feels a little odd to have a constructor overload purely for testing reasons, perhaps just to me it feels more obvious to supply the dependency through the existing test mechanism.

Looking at the original code ([src/Dapr.Actors/Runtime/ActorManager.cs]):

var host = new ActorHost(this.ActorTypeInfo, actorId, this.jsonSerializerOptions, this.loggerFactory, this.proxyFactory, this.timerManager)
{
    StateProvider = new DaprStateProvider(this.daprInteractor, this.jsonSerializerOptions),
};

The StateProvider is always set, so perhaps cleaner to supply through the constructor and make the property have a getter only (I did this in the PR)?

Anyways let me know your thoughts as I burnt far too much time looking in the wrong place :-) Once decided I'll knock some docs together to help others.

Thanks

TheRubble avatar Feb 18 '22 08:02 TheRubble

@TheRubble - Are you still working on this?

halspang avatar Aug 29 '22 21:08 halspang