Getting instance of class used to create an actor in Akka in test - scala

How do I get instance of class I passed to Props when creating an actor with ActorSystem.actorOf? I need that for unit tests to get reference to some properties of the actor, so the actor is local in the same JVM as test.
I don't want to use Akka's test framework because I need the actor live, it's kind of integration tests.

The underlying instance of an Actor subclass is well and truly sealed off from you and you're not going to get at it without mucking with Akka code itself. If you look at the definition of the ActorRef you'll see that it doesn't even contain a reference to the Actor!
Similarly, you cannot instantiate Actor subclasses directly using new.
I guess the Akka designers were serious about the ActorRef / Actor firewall...

The Akka Testkit is made for integration testing. To get access to the internal state of an actor send it a message asking for it. Your actor can reply to the sender which is the TestKit's testActor.

Related

How can I make an actor class to observable in scala

I've tried to make my actor class observable (extends Actor with Observable[T]). However, there is an error message that I have to implement the asJavaObserver value but there is no asJavaObserver in observable trait.
Aren't you mixing two separate programming paradigms? Actors only communicate by messages. So if anyone is interested in the state change of an actor it must receive a message from the actor.
The observable stuff is for other OO programs which don't use Actor model.

How to get a reference to an existing actor from a non-actor in Akka?

In my application, I have a class which needs to communicate with an existing actor already created in an actorSystem. How do I get a reference to that actor from this non-actor class?
If you have the reference to the actor system (https://doc.akka.io/api/akka/current/akka/actor/ActorSystem.html), then you can simply invoke actorSelection with the path of the actor. This will give you an ActorSelection, on which you can call resolveOne, and then wait until you get the reference of the actor. Once you have the actor reference, you can send messages to it.
Here is more information about addressing actors: https://doc.akka.io/docs/akka/current/general/addressing.html .

Unit Testing Components that Uses an Akka Actor

First of all, I am not asking how to unit test an Akka Actor. I know the techniques to do that. My problem is slightly different.
I am developing a Scala program, let's call it the client, that does not use Akka Actors. However, the program uses a library, let's call it the server, whose interface is implemented using an Akka Actor.
Then, through the ask pattern, the client interacts with the server.
// This is the client program
class Client(uri: String) {
implicit val context: ActorSystem = ActorSystem("client-actor-system")
private val mainActor = context.actorSelection(uri)
def connect: Future[SomeClass] = {
implicit val timeout: Timeout = Timeout(5 seconds)
(mainActor ? Connect()).mapTo[CreationResponse]
}
}
Now, I want to write down some unit tests for Client class. Unit testing means to test a class in isolation. Every external dependency should be mocked.
How can I mock the reference to mainActor inside Client class? How can I inject in the actor system a mock actor for mainActor?
Thanks in advance.
I would inject the mainActor actor selection into the client, and create that using Akka TestKits.
Of course, you need an ActorSelection, not an ActorRef. Some solutions for that can be found here:
Giving an ActorPath for a testProbe
Or alternatively, you could make mainActor an ActorRef by sending an Identify message to the ActorSelection.

Akka Actor Customization for libraries

I want to make a library that is going to be used and configurable by other people, using akka actors.
I want to make a Repository actor to which a type of storage will be injected by the library user like "MemoryDatabase" or "FileDatabase" or anything that extends a defined class or actor (see question 2).
1) What is the best way for a user to specify options (including his own created ones)?
2) Should "MemoryDatabase" be an actor child of repository, or just a normal class as a field/property of the Repository actor in this case?
Thanks!
-Jojolepro
Edit:
I want to make an actor that looks like
class Repository extends Actor{
val repoType:DataStorageType = ...
def receive:Receive={}
}
What I want to know the best way for a end user of such library to specify the repoType field, considering that Repository is already in a predefined actor hierarchy.
It depends on if you want the user to put in a concrete instance or merely a type. Ignoring any kind of DI system you could use, I would merely pass the concrete instance to the actor's constructor via props when the actor is started but then that would depend on the concrete instance being thread safe because not necessarily only that actor would be managing it. If you want the actor to own the repository, have the user pass the factory instance or type to the props and thus the constructor.

How to start Akka Actors since 2.0?

I'm using Akka Actors and I'm trying to update my code to use the latest 2.0 milestone. The API changed somewhat, for example the creation of Actors now works via something called an ActorSystem.
Starting and stopping actors changed as well - the latter is available via the ActorSystems methods .stop(..) and .shutdown(). But I can for the life of me not figure out how to start them...
The documentation is good, but seems to be missing some important points. I feel kinda stupid to ask, but how do you start actors in your Akka 2.0 environment? If I understood correctly actors who have a 'parent' are started when this parent is started - but what about the top level actor(s)?
In Akka 2.0, there is no need for a start() method because Actors are started as soon as you instantiate them in the context of an ActorSystem (or another Actor) -- but you need to instantiate them with one of the provided methods of ActorSystem or an Actor's context.
So, for example, if you have an Actor subclass called MyClass, you could start it with:
val system = ActorSystem()
val myActor = system.actorOf(Props[MyActor])
or, if your actor took constructor arguments:
val myActor = system.actorOf(Props(new MyActor("arg1"))
or, if you were in the body of another Actor,
val myActor = context.actorOf(Props(new Actor("arg1"))
and then your actor could immediately receive messages, e.g.
myActor ! MyMessage
Even your top level actors are started immediately, as all Actors in 2.0 are automatically in a supervision hierarchy. As soon as the actor is instantiated with the ActorSystem, it's ready to receive messages.