Reputation: 455
I'm new to using scala on the akka system.
I have a parent actor (named "manager") which sends a message to a child, and receives an answer, which it forwards to next child. The final actor saves the result of the whole process.
I want to create an end to end test which sends a message to the parent ("manager"), and expect a message from the last actor which recieves the result. I'm looking for a simple way to direct the final actor to send a message back to the test. Since the test is not the sender, and it's not a simple actor, i don't know how to direct the message correctly.
Following is code of the test:
class EndToEndTest extends TestKit(ActorSystem("MyActorSystem"))
with FunSuiteLike with Matchers with BeforeAndAfterAll with ImplicitSender {
override def afterAll {
TestKit.shutdownActorSystem(system)
}
test("should send result") {
val actor = system.actorOf(Props(new Manager(name = "ActorManager")))
actor ! tPoint(1000L)
actor ! tPoint(2000L)
expectMsg(ActorResult(1))
}
}
and of the last child actor:
class SensorHealthReportMySqlActor extends Actor with ActorLogging {
def receive = {
case Result(result: Long) =>
//this is where i would like to send the test a message with Result(result)
case _ =>
log.error("Unknown message type")
}
}
Any help would be appreciated.
Upvotes: 1
Views: 234
Reputation: 751
I think the solution you want is to pass an ActorRef
as a parameter in a message so the receiver knows where to send the reply when the message should be sent to some actor other than the sender of the current message.
So something along these lines:
import akka.actor.{Actor, Props, ActorRef, ActorLogging}
case class tPoint(n: Long)
case class Result(result: Long, replyTo: ActorRef)
case class ActorResult(result: Long)
class Manager(name: String) extends Actor {
val child = context.actorOf(Props(new SensorHealthReportMySqlActor))
override def receive: Receive = {
case msg: tPoint ⇒
child ! Result(msg.n, sender())
}
}
class SensorHealthReportMySqlActor extends Actor with ActorLogging {
def receive = {
case Result(result: Long, replyTo: ActorRef) =>
//this is where i would like to send the test a message with Result(result)
replyTo ! ActorResult(1)
case _ =>
log.error("Unknown message type")
}
}
In this case the sender()
in the Manager
receive
method is the test itself, which is an ImplicitSender
(as you declared in your test). This is an actor created behind the scenes which can receive messages.
In a non-test system, you can use the ask
pattern or an Inbox
for this same purpose. See the documentation at Actors.
Upvotes: 2