javaakkapowermocktestkit

powermockito for private methods in akka actors


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?


Solution

  • 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.