如何模拟未来的onComplete方法?

时间:2014-06-04 17:06:37

标签: scala akka mockito specs2

我有一个Akka演员,它使用包含未来的消息。以下是它的简化版本:

case class MyMessage(s: Future[String])

class MyWorker extends Actor {
  override def receive: Receive = {
    case MyMessage(future) =>
      future onComplete {
        case Success(s) => sender ! s
        case Failure(e) => throw e
      }
  }
}

我正在使用TestActorRef在specs2中测试它,但是当我编写这样的规范时:

class MyWorkerSpec extends Specification with Mockito {

  val worker = TestActorRef(new MyWorker)

  "MyMessage" should {

    "return the string from a successful result" in {
      val message = MyMessage(Future("test"))
      val result = worker ? message
      result.value.get must_== Success("test")
    }

  }
}

...然后它以NoSuchElementException: None.get失败,并且Akka系统抱怨死信。

认为这可能是因为它不等待未来完成,我决定尝试嘲笑未来并抄袭onSuccess方法。我不知道怎么做,因为func参数显然是Any

class MyWorkerSpec extends Specification with Mockito {

  val worker = TestActorRef(new MyWorker)

  "MyMessage" should {

    "return the string from a successful result" in {
      val mockFuture = mock[Future[String]]
      mockFuture.onComplete(any[Try[String] => String]) answers {
        func => {
          func(Success("test"))
        }
      }
      worker ! MyMessage(mockFuture)
    }
  }
}

如何嘲笑这样的未来?或者有更好的方法吗?

1 个答案:

答案 0 :(得分:4)

我认为这里不需要任何嘲弄。

1-如何创建这样的FutureMyMessage(Future.successful("test")),这样就可以在您创建时完成。

2-在value上致电result之前,您应该等待您的演员回复:

val result = worker ? message
Await.result(result, duration) must_== Success("test")

请参阅:http://www.scala-lang.org/api/current/index.html#scala.concurrent.Await$

3-向演员发送Future的实例对我来说听起来很糟糕。