0

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?

user_mda
  • 18,148
  • 27
  • 82
  • 145

1 Answers1

2

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.

Danylo Zatorsky
  • 5,856
  • 2
  • 25
  • 49
  • Ideally, it's another interface of the class (following dependency inversion principle from SOLID). But whenever it's beans for internal use only (e.g when you do not build a library or API used by others) my personal opinion is that having it as a separate class without interface would be sufficient. – Danylo Zatorsky Mar 24 '18 at 19:42