0

In book of akka in actor's chapter three. It use a message event to test silent actor's state.

The actor as this:

object SilentActorProtocol {
 case class SilentMessage(data: String)
 case class GetState(receiver: ActorRef)
}
class SilentActor extends Actor {
 import SilentActorProtocol._
 var internalState = Vector[String]()
 def receive = {
   case SilentMessage(data) =>
     internalState = internalState :+ data
     case GetState(receiver) => receiver ! internalState
   }
}

Test code as this:

"change internal state when it receives a message, multi" in {
 import SilentActorProtocol._
 val silentActor = system.actorOf(Props[SilentActor], "s3")
 silentActor ! SilentMessage("whisper1")
 silentActor ! SilentMessage("whisper2")
 silentActor ! GetState(testActor)
 expectMsg(Vector("whisper1", "whisper2"))
}

Inner the test code why use GetState get result of above SilentMessage event.
Why not use slientActor.internalState get the result straightly?

Update

Some friends seems mislead my problem.For detail, The books said

use the internalState variable will encounter concurrency problem, so there should use a GetState event tell actor to get the actor's inner state rather then use internalState straightly.

I don't know why it should encounter concurrency problem and why use GetState can fix the problem

Explain

slientActor.internalState can't get inner variable straightly , instand, use silentActor.underlyingActor.internalState can get it.So sorry for the terrible question.

Community
  • 1
  • 1
LoranceChen
  • 2,453
  • 2
  • 22
  • 48

1 Answers1

1

If I understand your question correctly, the answer is that the silentActor in the test code is not the actor, it is the ActorRef instance, therefore it does not have the internalState var to be referenced.

If you want to write unit tests for specific variables and methods on the ActorRef, you need to use the underlyingActor technique as described (with its caveats) in the documentation. (see section on TestActorRef.

Reza
  • 847
  • 6
  • 14
  • In this situation SilentActor has a `internalState` variable and I'm not change the code form book. So,why not check by `internalState`? – LoranceChen Jul 12 '16 at 06:46
  • But it does not have an internalState variable. In your test code, the val silentActor is created by a call to system.actorOf(...). this will return an ActorRef Instance, which will not have the properties of the SilentActor class. – Reza Jul 12 '16 at 18:20
  • I really define it ... `var internalState = Vector[String]()`. search the code in current page will find it. – LoranceChen Jul 13 '16 at 01:03
  • 1
    I will try to explain one last time. your definition is in the class, not the instance. you don't have a "new SilentActor()" in your code, do you? in fact, you can't have that at all. so you don't have an instance of SilentActor anywhere to access internalState. what you have is an instance of ActorRef, which you have called silentActor. that doesn't have an internalState, because it is NOT an instance of SilentActor. – Reza Jul 13 '16 at 03:06
  • `silentActor.underlyingActor.internalState` can get it. So sorry for my code >.<. Now, why not use the sentence above? I will update the problem – LoranceChen Jul 13 '16 at 05:31
  • No problem. So using underlyingActor will actually test your code in synchronized mode (no new threads will be created), and it is probably your first step and to make sure that the internal mechanisms will work correctly. However, once you are past that point, you need to test it in async mode (by sending messages to it) to make sure you won't run in concurrency problems as you have quoted in your original post. if your actor, for example, causes live or deadlocks, then underlyingActor testing won't catch it, but sending messages to it will catch that. makes sense? – Reza Jul 13 '16 at 19:52
  • In other word, send message make sure event be done as sequence they create. but underlyingActor not follow any sequence so it maybe done before "whisper2" message send.I think I got it.Thanks your patient explanation.:) – LoranceChen Jul 14 '16 at 00:51