I need some support in order to uderstand how I could successfully wait for an expected response message that is sent from within an actor Receive block.
The following example is different to what I could find so far in the web, because I use the Akka.Cluster / Akka.Cluster.Tools
to Publish Messages instead of sending a message directly back 'Sender.Tell()
' to the sender.
Question: How can I fetch, subscribe etc. this published SomeResponse
message in my Unit Test?
public class SomeRequest { }
public class SomeResponse { }
public class MyDbTestActor : ReceiveActor
{
private readonly IActorRef _mediator;
public MyDbTestActor()
{
// ...
_mediator = DistributedPubSub.Get(Context.System).Mediator;
// ...
Receive<SomeRequest>(o =>
{
// ...
var response = new SomeResponse();
_mediator.Tell(new Publish(Global.MYTopic, response)); // <-- ExpectMsg timeout ...
//Sender.Tell(response); // if uncommented ExpectMsg is succeed.
});
}
}
class Global
{
public static string MYTopic =nameof(MYTopic);
}
public class SomeActorTests : TestKit
{
[Fact]
public void SomeTest()
{
var actor = Sys.ActorOf(Props.Create<MyDbTestActor>());
actor.Tell(new SomeRequest());
ExpectMsg<SomeResponse>();
}
}
I would just have the TestActor
subscribe to that topic from the DistributedPubSub
mediator:
public class SomeActorTests: TestKit
{
private IActorRef _mediator;
private string path;
// pass in an Akka.Cluster config that performs a self-join, etc
public SomeActorTests(Config config, ITestOutputHelper output) : base(config, output:output)
{
_mediator = DistributedPubSub.Get(Sys).Mediator;
}
[Fact]
public void SomeTest()
{
// arrange
var actor = Sys.ActorOf(Props.Create<MyDbTestActor>());
_mediator.Tell(new Subscribe(Global.MYTopic, TestActor));
ExpectMsg<SubscribeAck>(); // subscription confirmed
// act
actor.Tell(new SomeRequest());
// assert
ExpectMsg<SomeResponse>();
}
}
That will close the circuit using the Mediator
to connect your actor and the TestActor
together.