I have the following actor
import akka.actor.AbstractActor;
import akka.event.Logging;
import akka.event.LoggingAdapter;
public class MyActor extends AbstractActor {
private final LoggingAdapter log = Logging.getLogger(getContext().getSystem(), this);
@Override
public Receive createReceive() {
return receiveBuilder()
.match(String.class, s -> {
log.info("Received String message: {}", s);
doSomethingNow();
})
.matchAny(o -> log.info("received unknown message"))
.build();
}
private MyObject doSomethingNow() {
/// code
return MyObject;
}
Now to unit test this actor, should I mock the method 'doSomethingNow'? From the PowerMockito doc, it looks like I also need to mock the class which is the actor but the TestKit already offers a framework around mocking actors, whats the right way to test this actor?
The best thing you could do here is to use dependency injection. Ideally - your actors shouldn't contain any business logic in them - they need to route the message to the underlying services.
In your case you could have a separated service, e.g DoerService
with doSomethingNow
method in it. Then you can inject it via dependency injection framework of your choice, as shown below:
import akka.actor.AbstractActor;
import akka.event.Logging;
import akka.event.LoggingAdapter;
public class MyActor extends AbstractActor {
private final LoggingAdapter log = Logging.getLogger(getContext().getSystem(), this);
@Inject
private DoerService doerService;
@Override
public Receive createReceive() {
return receiveBuilder()
.match(String.class, s -> {
log.info("Received String message: {}", s);
doerService.doSomethingNow();
})
.matchAny(o -> log.info("received unknown message"))
.build();
}
This way you do not even need Powermock to accomplish your task. Mockito will be more than enough.
IMHO, whenever Mockito is not enough to unit test your code then most likely something is wrong with your design. A code should be not only well written and reusable - it should also be testable.