How do I mock a future's onComplete method?

akka, mockito, scala, specs2

Solution

I don't think there is any mocking required here.

1- How about creating your `Future` like this: `MyMessage(Future.successful("test"))`, that way it is completed when you create it.

2- You should wait for your actor to reply before calling `value` on `result`:

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

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

3- Sending an instance of `Future` to an actor sounds like a terrible idea to me.

Problem

I have an Akka actor that works with a message containing a future. Here is a simplified version of it: ``` 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 } } } ``` I am using TestActorRef to test it in specs2, but when I write a spec like this: ``` 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") } } } ``` ...then it fails with `NoSuchElementException: None.get`, and the Akka system complains about dead letters. Figuring that this is probably because it isn't waiting for the future to complete, I decided to try mocking the future and stubbing the `onSuccess` method. I'm not sure how to do this, though, because the `func` argument is evidently an `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) } } } ``` How does one mock a future like this? Or is there a better way to do it?

Original source