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



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

MyActor类

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的答案相关:我写这个单元测试的原因是学术性的,但事实上,这不是一个好的单元测试,这就是为什么你不能像我希望的那样做。摘自Pet删节的单元测试指南:

事实上,如果一个参与者想知道另一个参与者的内部状态,那么它必须向该参与者发送一条信息。我建议您在测试中遵循相同的模式,不要滥用TestActorRef。在测试中坚持应用程序中实际使用的消息传递模型。

您可以通过消息传递进行正常测试。例如,您在"已启动"状态下处理哪些消息?我假设您的示例已经简化为Started中的Console.WriteLine操作。

如果您先发送StartMessage,然后再发送第二条在"已启动"状态下处理的消息,则可以对第二条消息的响应进行断言。

作为一个简单的建议:

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

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

欲了解更多信息,请查看Petdeplete文章https://petabridge.com/blog/how-to-unit-test-akkadotnet-actors-akka-testkit/

最新更新