如何对 Akka.Net Actor 状态进行单元测试(使用 Become())

How to unit test Akka.Net Actor State (using Become())

我有一个 Actor,当它收到 StartMessage 时,它应该使用 Become(Started) 改变状态。如何对 Actor 的状态是否已更改为 Started() 进行单元测试?

我的演员class

public class MyActor : ReceiveActor
{
    public MyActor()
    {
        Receive<StartMessage>(s => {
            Become(Started); // This is what I want to unit test
        });
    }

    private void Started()
    {
        Console.WriteLine("Woo hoo! I'm started!");
    }
}

单元测试

        [TestMethod]
    public void My_actor_changes_state_to_started()
    {
        // Arrange
        var actor = ActorOfAsTestActorRef<MyActor>(Props.Create(() => new MyActor()));

        // Act
        actor.Tell(new StartMessage());

        // Assert
        var actorsCurrentState = actor.UnderlyingActor.STATE; // <-- This doesn't work
        Assert.AreEqual(Started, actorsCurrentState);
    }

更新

与 tomliversidge 的回答有关:我写这个单元测试的原因是学术性的,但实际上,这不是一个好的单元测试,这就是为什么你不能像我希望的那样做。来自 Petabridge's Unit Testing Guide:

In reality, if one actor wants to know the internal state of another actor then it must send that actor a message. I recommend you follow the same pattern in your tests and don’t abuse the TestActorRef. Stick to the messaging model in your tests that you actually use in your application.

你通常会通过消息传递来测试这个。例如,您在 Started 状态下处理哪些消息?我假设您的示例已简化为 Started.

中的 Console.WriteLine 操作

如果您先发送 StartMessage,然后再发送一条在 Started 状态下处理的消息,您就可以断言对第二条消息的响应。

作为一个简单的建议:

private void Started()
{
    Receive<StartMessage>(msg => {
        Sender.Tell(new AlreadyStarted());
    } 
}

如果在 Started 状态下接收到 StartMessage,您可以断言接收到 AlreadyStarted 消息。

有关详细信息,请查看 Petabridge 文章 https://petabridge.com/blog/how-to-unit-test-akkadotnet-actors-akka-testkit/