2

At present examples are sparse on unit testing SF actors, and I'm currently trying to get my head around what is the correct/best way to test the framework-provided features SF actors (state,reminders,timers etc).

One part of my brain (the way that I usually work) is telling me to unit test everything inside the actor seperately and integration test the boundaries of the actor. However I got a feeling that im going against the actor framework to do this.

For instance, for state management, I feel like I want to do something like as described in the 'New' method below and abstract-away the stateManager :

public class MyActor : Actor, IMyActor
{
    private readonly IWidgetStore _widgetStore; 
    private readonly ISomeLogic _someLogic; 

    public MyActor(service, id, widgetStore, someLogic) : base(service, id){
         _widgetStore = widgetStore;
    }

    public Task New(int x, int y){
         var result = _someLogic.Calculate(x,y);
         _widgetStore.Upsert(result); 
    }

    public Task Old(int x, int y){
         var result = _someLogic.Calculate(x,y);
         this.actorStateManager.AddOrUpdateStateAsync("widget_state", result, (s, s1) => result).Wait(); 
    }
}

public class WidgetStore : IWidgetStore
{
     private readonly IActorStateManager _actorStateManager;

     public WidgetStore(IActorStateManager actorStateManager)
     {
          _actorStateManager = actorStateManager;
     } 
     public Task Upsert(string value)
     {
          _actorStateManager.AddOrUpdateStateAsync("widget_state", value, (s, s1) => value).Wait();
     }
}

Doing this feels right, but I need a gaurantee that my widgetStore unit is actually working correctly and state is being persisted.

Two options

  1. Write a widgetStore unit test that verifies calls against the StateManager methods. Obviously this doesnt actually call the real implementation, but is the 'verify' suffice? I feel like I should be able to rely on the framework to actually do what its supposed to do... You as a consumer of the addition operator wouldn't write a test against the adddition operator to prove that 1 + 1 = 2 would you?
  2. Write a suite of tests that cover integrating against the real actor framework (with the runtime running on a local cluster). I will integrate against the real stateManager, and effectively black box test the Actors behavior using ActorProxy. If the behavior tests pass, then I must be storing state correctly? This feels better, but isn't this turning out to be an acceptance test?

As I draft this question, I feel like I should taking an approach to testing Actors which typically goes against how I have unit tested my services in the past.

I feel like I should be embracing actor framework & runtime as one holistic unit and test from a behavioral perspective, as described in Option 2.

I'm now looking to you, the SF community, for discourse and recommendations on this.

Edit

If I was to abstract the statemanager behind the widgetStore unit, there is no friendly way to get at the stateManager prior to Actor construction, so now I gotta do something like this (in the ActorRuntime.RegisterActorAsync method)...

Func<ActorService, ActorId, ActorBase> actorFactory = (service, id) =>
{
      var widgetStore = new WidgetStore();
      var someLogic = new SomeLogic();

      var actor = new MyActor(service, id, widgetStore, someLogic);

      widgetStore.Inject(actor.StateManager);

      return actor;
};

This feels hacky as I now have to expose a method on the widgetStore to inject the stateManager, as you can't get at the stateManager prior to actor construction.

Flimzy
  • 60,850
  • 13
  • 104
  • 147
Oliver Tomlinson
  • 505
  • 1
  • 3
  • 17
  • 1
    Integration tests and unit tests both serve a purpose right? Do both. Make sure to mock the statemanager in option 1. Have a look at: http://stackoverflow.com/questions/5357601/whats-the-difference-between-unit-tests-and-integration-tests – LoekD Sep 29 '16 at 08:46

0 Answers0