Unit Test Service Fabric Actors when Actors call other Actors
In order to be able to effectively unit test Azure Service Fabric Actors we use a NuGet package called “ServiceFabric.Mocks”. It’s truly fantastic. As the name implies it allows you to Mock all Service Fabric services, not just Actors but the Actor model has unique structure that makes it exceptionally helpful in testing.
The way it works is when you are going to get an instance of an actor within a Unit Test you need to use the MockActorServiceFactory.CreateActorServiceForActor
Using the MockActorServiceFactory to get an instance of an actor (and activate it). This will add the actor to the factory such that when you request the actor it will be returned. But what happens when that actor needs to call another actor?
First, you need to provide a mechanism to provide an alternative IActorProxyFactory to your Actor. Your actor will need to use its own copy of the IActorProxyFactory to create actor instances instead of some of the static helper methods that are common within Service Fabric Actor samples.
You’ll notice that the proxy factory is passed in as an optional parameter to the Actor’s constructor. If its null, it will create a new ActorProxyFactory, which is the default way Service Fabric works and the way it will work in production. In production this optional parameter will always be null. However, in our unit tests we have the option of side loading a Mock Proxy Factory.
You’ll notice that the actor we activate, we end up registering with the proxy factory, this is kind of like pre-initializing the actor within the ProxyFactory, such that when the actor is requested, the proxy factory will give it up.
This works when you explicitly add an actor at the start of your test but what happens when you need to add an actor dynamically at runtime DURING your test? The MockActorProxyFactory has a solution! the MissingActory event. This event will fire whenever an actor is requested (using an ActorId) that does not have an Actor object already registered. This event gives you a chance to create an instance of that actor, activate it and register it with the ProxyFactory.
this is important because many times when an actor ‘A’ calls another actor ‘B’, you don’t know what the actor ID will be for Actor B at the start of your unit test. The MissingActor event allows you to passively response to actor requests and let actor ‘A’ pass in the expected actor ID when I asks for an instance of Actor ‘B’. Make sure you pass in the MockActorProxyFactory to your dynamically created Actor just in case it also needs to request additional actors.
Hope this helps! Unit Test Actors can be daunting at first but with ServiceFabric.Mocks it is really easy!