Reputation: 2763
I've designed an actor that should send its' actorRef to another actor on prestart:
class MyActor(notifier: ActorRef) extends Actor {
override def preStart(): Unit = {
notifier ! Register(self)
}
...
}
case class Register(actor: ActorRef)
Then I've written a specification for this Actor:
class MyActorSpec extends TestKit(ActorSystem("MyActorSpec"))
with ImplicitSender
with WordSpecLike
with Matchers
with BeforeAndAfterAll {
"MyActor" should {
val notifier = TestProbe()
"register itself in notifier" in {
val myActor = system.actorOf(Props(classOf[MyActor], notifier.ref))
notifier.expectMsg(Register(myActor))
}
}
}
When I run my test, it fails with the following message: assertion failed: expected Register(Actor[akka://MyActorSpec/user/$b#1849780829]), found Register(Actor[akka://MyActorSpec/user/$a#1143150267])
So, it seems that ActorRef obtained via self
inside MyActor is not equal to ActorRef obtained via system.actorOf
in my test. Any suggestions?
Upvotes: 2
Views: 242
Reputation: 2763
I've figured it out. It was because I've used shared TestProbe in several test cases, in which I create different instances of MyActor.
class MyActorSpec extends TestKit(ActorSystem("MyActorSpec"))
with ImplicitSender
with WordSpecLike
with Matchers
with BeforeAndAfterAll {
"MyActor" should {
val notifier = TestProbe()
"register itself in notifier" in {
val myActor = system.actorOf(Props(classOf[MyActor], notifier.ref))
notifier.expectMsg(Register(myActor))
}
"do some useful work" in {
val myActor = system.actorOf(Props(classOf[MyActor], notifier.ref))
....
}
}
}
Instead, using a fresh instance of TestProbe for each test case helped.
class MyActorSpec extends TestKit(ActorSystem("MyActorSpec"))
with ImplicitSender
with WordSpecLike
with Matchers
with BeforeAndAfterAll {
"MyActor" should {
"register itself in notifier" in {
val notifier = TestProbe()
val myActor = system.actorOf(Props(classOf[MyActor], notifier.ref))
notifier.expectMsg(Register(myActor))
}
"do some useful work" in {
val notifier = TestProbe()
val myActor = system.actorOf(Props(classOf[MyActor], notifier.ref))
....
}
}
}
Anyway, thanks to all for proving that for single test case it works well.
Upvotes: 0
Reputation: 31724
The code you posted ideally should not even compile at:
val myActor = system.actorOf(Props(classOf[MyActor], notifier))
Because the constructor expects an ActorRef
which we are not passing. But correcting it, it works:
class MyActorSpec extends TestKit(ActorSystem("MyActorSpec"))
with ImplicitSender
with WordSpecLike
with Matchers
with BeforeAndAfterAll {
"MyActor" should {
val notifier = TestProbe()
"register itself in notifier" in {
val myActor = system.actorOf(Props(classOf[MyActor], notifier.ref))
notifier.expectMsg(Register(myActor))
}
}
}
For a second, just to make sure that there is no special magic happening because of ActorProbe
, I wrote plain old actor class below.
object Prac {
def main(args: Array[String]) {
val system = ActorSystem("HelloSystem")
val myActor = system.actorOf(Props(classOf[MainActor]))
}
}
class MyActor(notifier: ActorRef) extends Actor {
override def preStart(): Unit = {
notifier ! Register(self)
}
override def receive: Receive = {
case x => println("My Actor ->"+x)
}
}
case class Register(actor: ActorRef)
class MainActor extends Actor{
val actor = context.actorOf(Props(classOf[MyActor], self))
override def receive = {
case Register(x) =>
println(actor == x)
context.system.shutdown()
}
}
And it prints true
. So there is nothing wrong with your programme.
Upvotes: 1
Reputation: 1782
The following code is working just fine for me (the test passes):
class MyActor(notifier: ActorRef) extends Actor {
override def preStart(): Unit = {
notifier ! Register(self)
}
override def receive: Receive = {
case _ =>
}
}
case class Register(actor: ActorRef)
class MyActorSpec extends TestKit(ActorSystem("MyActorSpec")) with ImplicitSender with WordSpecLike with Matchers with BeforeAndAfterAll {
"MyActor" should {
val notifier = TestProbe()
"register itself in notifier" in {
val myActor = system.actorOf(Props(new MyActor(notifier.ref)))
notifier.expectMsg(Register(myActor))
}
}
}
Upvotes: 1