如何同步对akka Actor进行单元测试?

时间:2014-01-03 18:05:09

标签: unit-testing scala akka actor

我有一个演员在收到一定数量的短信后会写一个文件。

编译时,Maven会运行我们定义的所有单元测试。问题是,在Actor写入文件(它正确执行)之前,检查文件是否已成功写入磁盘的单元测试。

我找到了一些测试演员的文档,但它们都已经过了好几年了。在检查文件是否存在之前,我该如何等待?

2 个答案:

答案 0 :(得分:4)

总结所有意见和建议:

  • 将非演员特定代码重构为常规类,并使用常规方法(单元测试等)对其进行测试。这更像是一种单元测试方法。
  • 使用TestActorRef测试单个actor - 您可以同步控制事件并丰富到actor内部。使用提供更多功能的TestKit,包括“特殊”演员系统。这更像是一种行为测试方法。
  • 使用文档here了解有关Akka TestKit如何工作的更多信息,但总之,您可以控制您的actor和同步执行。

答案 1 :(得分:2)

对于同步actor测试,请使用与此类似的TestProbes(akka.testkit):

import org.scalatest.{FunSuite, BeforeAndAfterAll}
import org.scalatest.matchers.ShouldMatchers
import scala.concurrent.duration._
import scala.util.Random
import scala.util.control.NonFatal
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
import akka.actor.{ActorSystem, ActorRef, Actor, Props}
import akka.testkit.{TestKit, ImplicitSender, TestProbe}
import scala.concurrent._
import ExecutionContext.Implicits.global

@RunWith(classOf[JUnitRunner])
class Example extends TestKit(ActorSystem("filetest"))
  with FunSuite
  with BeforeAndAfterAll
  with ShouldMatchers
  with ImplicitSender
  with Tools {

  override def afterAll(): Unit = {
    system.shutdown()
  }

  test("Show synchronous actor test") {
    val tester = TestProbe()
    val fileActor = system.actorOf(Props(classOf[FileActor]), "case2-primary")

    tester.send(fileActor, CreateFile(1))
    tester.expectMsg(FileCreated(1)) // Will synchronously wait (~500ms in this example)
  }
}

case class CreateFile(id: Long)
case class FileCreated(id: Long)

class FileActor extends Actor {
  def receive = {
    case CreateFile(id) => {
      val s = sender
      createFile(id).map( id => s ! FileCreated(id))
    }
  }

  def createFile(id: Long): Future[Long] = future {
    // "Create" the file...
    Thread.sleep(500)
    id
  }
}