7

I have a Controller class which controls the requests sent to a Akka actor which is injected in to the controller.

Controller's code:

class Controller(actor: ActorRef) {
  def control(msg: String): Future[String] = {
    actor.ask(msg)(Timeout(2 seconds)).mapTo[String]
  }
}

And my Actor's code is:

class ActorA extends Actor {
  override def receive: Receive = {
    case msg: String => sender ! msg
    case msg: Int => sender ! msg.toString
    case _ => "Invalid command!"
}

Now I need to mock ActorA's behaviour to unit test Controller. Is there a way to do so via Akka TestKit ?

himanshuIIITian
  • 5,985
  • 6
  • 50
  • 70

1 Answers1

15

Use a TestProbe. From the testing documentation:

val probe = TestProbe()
val future = probe.ref ? "hello"
probe.expectMsg(0 millis, "hello") 
probe.reply("world")
assert(future.isCompleted && future.value == Some(Success("world")))
Ramón J Romero y Vigil
  • 17,373
  • 7
  • 77
  • 125
  • Thanks @ramon for the response. It explains a lot about **TestProbe()** usage. But can I provide **probe.ref** to Controller and assert result of **control**, I mean something like this: `val controller = new Controller(probe.ref); val result = Await.result(controller.control("hello"), 2 seconds); assert(result.isCompleted && result.value == Some(Success("world")))` – himanshuIIITian Dec 14 '15 at 15:37
  • 2
    @himanshuIIITian You are welcome. Yes you can use probe.ref in the way you specified, but in your unit testing code after `val probe = TestProbe()` you have to add something like `probe.expectMsg(500 millis, "hello")` and `probe.reply("hello")` so that the probe behave the same way as you expect the Actor to behave. Happy hacking! – Ramón J Romero y Vigil Dec 14 '15 at 19:30
  • Hi, @ramon. I tried it the way you specified in previous comment. But, got no success with it as I keep on getting `Timeout Exception` for `val result = Await.result(controller.control("hello"), 2 seconds)`. So, I got it working with `TestActorRef(new ActorA {override def receive: Receive = {case msg:String => sender ! msg ...}})`. I know that we are redefining `receive` for ActorA, but it behaves in the way I want to. – himanshuIIITian Dec 15 '15 at 07:06
  • 1
    I suspect it's an ordering problem. As the docs demonstrate the `expectMsg` call has to come after the `?` to probe. But, at least you got something working... – Ramón J Romero y Vigil Dec 15 '15 at 10:34