我有一个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/