Mockito and Guice : mocking a @Provides method

Sasanka Panguluri picture Sasanka Panguluri · Dec 12, 2014 · Viewed 14.1k times · Source

I have a module in my class called MainModule. It has various bindings in it, one of which is a binding to my custom service interface called HttpClientPool

public class MainModule extends AbstractVertxModule{
        binder.bind(HttpClientPool.class).to(HttpClientPoolImpl.class).in(Singleton.class);
        // other bindings
} 

@Provides @Singleton
    public TokenClient tokenClient(HttpClientPool clientPool){
        return new TokenClient(clientPool);
}

The module is also a provider of an object called tokenClient, as seen above.

The tokenClient is being injected somewhere else in a different class and a few methods are being invoked on this object.

In my unit tests, I'm intending to use Mockito to get a mocked tokenClient object. That means, I would like MainModule to provide a mocked object, instead of a real one. I have tried using a testMainModule that looks like this:

public class testMainModile implements Module{
    private TokenClient tokenClient;

    public TokenModule(TokenClient client) {
        this.tokenClient= client;
    }

    @Override
    public void configure(Binder binder) {
        binder.bind(TokenClient.class).toInstance(tokenClient);
    }
}

An excerpt from my unit tests:

@Mock
private TokenClient tokenClient;
// Stuff between
Injector messagingInjector = Guice.createInjector(new TestMainModule(tokenClient));
        mainModule = messagingInjector.getInstance(MainModule.class);

Somehow, all I get is a real object from the mainModule object. Am I missing something?

Answer

Jan Galinski picture Jan Galinski · Dec 14, 2014

I assume that you have a class that provides some functionality. This is the class you want to unit test. It requires a tokenClient that you inject into the class to work properly. So the question you are facing is: how does my class under test get a mocked tockenClient injected when I test it.

There are several possibilities ... possibly the easiest one is to strictly use constructor injection only and create the instances of your class under test via "new" and just hand them mocked instances created separately.

If you want to stick with guice, it is possible to override Bindings and Providers or even provide completely isolated test-modules.

I prefer using the needle4j framework (I am a contributor so I am biased), a dependency injection simulator that by default injects mocks unless configured to do otherwise. If used correctly (stick to one class unit, do not try to set up integration level tests), this might be the fastest and simpliest way to test classes depending on injected instances.