Is it possible to mock service which is created in class under test?

Viewed 438

I would like to be able to mock SomeService, however, because it's a maven plugin, I'm out of control how this class is created. I need to create SomeService manually, because I can't use it in constructor or in other place. In a test I can mock SomeService - but it will be replace by new instance created in execute() method. Is it possible to mock this service in other way than using PowerMockito ??

@Mojo(name = "hellomojo")
    public class HelloMojo extends AbstractMojo {    

     private SomeService service;    

     @Override
     public void execute() throws MojoExecutionException {     
        service = createService();
     }

     private SomeService createService() {
           return new SomeService(parameter);
     }
    }
4 Answers

My best guess would be to make createService() method package private and create HelloMojoWrapperForTests that overrides it and always returns mock. But this seems like a huge workaround just for the sake of testing...

Make createService() as protected and override this and return the mock in your test class while creating an anonymous class which extends HelloMojo. This way though your not testing the original class but a child of it but its pretty obvious that the child is just like the parent class except the overriden method which is intended.

public HelloMojoTest {    

     private HelloMojo helloMojo = new HelloMojo(){
   @Override
     protected SomeService createService() {
// return new or mocked or whatever instance you want
           return new SomeService();
     }
   }
 }

Extend the HelloMojo class in test and override the execute() method and give your implementation. Use this extended class for testing in unit tests(I am assuming Junits or something)

My final solution to this problem is following. First of all I've extracted service creation to separate class like :

public class ServiceProvider {

    public SomeService createService() {
        return new SomeService();
    }
}

Then, in my HelloMojo I've created two constructors, where default one uses constructor which set SomeService. Finally my HelloMojo class looks like :

    @Mojo(name = "hellomojo")
    public class HelloMojo extends AbstractMojo {    

     private SomeService service;  

    public HelloMojo(){
       this(new SomeService())      
    }   

    public HelloMojo(SomeService someService){
       this.service=someService;
    }   

     @Override
     public void execute() throws MojoExecutionException {     
        service.doSomething
     }             
    }

So, I've just did some dependency injection

Related