如何测试向其他演员发送消息的Akka演员? [英] How do I test an Akka actor that sends a message to another actor?
问题描述
我将ScalaTest与Akka TestKit结合使用,为我编写的演员编写单元测试和集成测试,以简单地将消息发送给另一个演员,而不会改变任何内部状态。例如:
I'm using ScalaTest with the Akka TestKit to write unit and integration tests for an actor I've coded to simply send a message to another actor without mutating any internal state. Take this for example:
class MyActor extends Actor {
val anotherActor = context.actorOf(Props[AnotherActor])
def receive: Receive = {
case MyMessage => anotherActor ! AnotherMessage
}
}
我想编写一个测试来确认 anotherActor
由于 MyActor
处理<$ c而处理了 AnotherMessage
$ c> MyMessage 。典型的示例是使用 TestActorRef
到达底层的actor并检查某些内部状态,该状态应在收到消息后受到影响,例如:
I want to write a test that confirms that anotherActor
processed AnotherMessage
as a consequence of MyActor
processing MyMessage
. The classic example is to use TestActorRef
to get at the underlying actor and check for some internal state that should have been affected upon message receipt like so:
val testActorRef = TestActorRef(new MyActor)
"MyActor" should "change some internal state when it receives MyMessage" in {
testActorRef ! MyMessage
testActorRef.underlyingActor.someState shouldBe "altered"
}
我的情况我不在乎这种状态。实际上,我要避免保持任何此类状态。 TestProbe
也不是我想要的,因为您仍然必须向演员注册 TestProbe.ref
在测试中。在大多数情况下,我查看了Akka文档中有关测试的所有示例( http://doc.akka.io/docs/akka/snapshot/scala/testing.html ),但找不到合适的东西。
But in my case I don't care about such state. In fact, I want to avoid holding any such state. TestProbe
wasn't quite what I was looking for either since you still have to register aTestProbe.ref
with the actor under test. For the most part, I've looked at all the examples in the Akka documentation on testing (http://doc.akka.io/docs/akka/snapshot/scala/testing.html) but haven't found anything suitable.
推荐答案
大概有几种方法可以实现,我将向您展示在我们有类似于测试的东西时可以工作的一种方法。我仍然认为 TestActorRef
, TestKit
和 TestProbe
是去。考虑以下结构:
There's probably a few ways to do this, I'll show you one that works when we have something similar to test. I still think TestActorRef
, TestKit
and TestProbe
are the way to go. Considering the following structure:
case object MyMessage
case object AnotherMessage
class MyActor extends Actor {
val anotherActor = createAnother
def receive: Receive = {
case MyMessage => anotherActor ! AnotherMessage
}
def createAnother = context.actorOf(Props[AnotherActor])
}
class AnotherActor extends Actor{
def receive = {
case _ =>
}
}
问题是您有一个actor实例创建了一个子演员,并且作为测试的一部分,即使您在测试中无法控制任何孩子的创建,也需要确保该子得到消息。遇到这种情况时,我们将执行以下类似的简单操作(使用specs2完成,但应该能够在ScalaTest中创建类似的东西):
The issue is that you have an actor instance creating a child actor and as part of your test you need to make sure that child gets a message even though you in your test don't have any control in the creation of that child. When we have this situation, we do something simple like the following (done using specs2, but should be able to create something similar in ScalaTest):
import akka.actor._
import akka.testkit._
import org.specs2.mutable.SpecificationLike
import org.specs2.runner.JUnitRunner
import org.junit.runner.RunWith
class MessageSendingSpec extends TestKit(ActorSystem("test")) with SpecificationLike{
val probe = TestProbe()
val myActor = TestActorRef(new MyActor{
override def createAnother = probe.ref
})
"Sending MyMessage to an instance of MyActor" should{
"pass AnotherMessage to the child AnotherActor" in {
myActor ! MyMessage
probe.expectMsg(AnotherMessage)
success
}
}
}
关键是在创建要测试的actor时,我将覆盖创建子级的方法以提供我的探针。它很粗糙,而且简单有效。
The key there is that when creating the actor to test, I override the method that creates the child in order to supply my probe. It's crude, but also simple and effective.
这篇关于如何测试向其他演员发送消息的Akka演员?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!