如何测试向其他演员发送消息的Akka演员? [英] How do I test an Akka actor that sends a message to another actor?

查看:88
本文介绍了如何测试向其他演员发送消息的Akka演员?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆