chris
chris

Reputation: 3

C# Akka.Net Unit Tests which built-In Assertion is the correct to wait for a published message?

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>();
    }
}

Upvotes: 0

Views: 345

Answers (1)

Aaronontheweb
Aaronontheweb

Reputation: 8394

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.

Upvotes: 0

Related Questions