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?
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.
The accepted answer suggests a number of approaches. If you need to override the binding (e.g. if you cannot modify MainModule
), here is a full working example:
class MainModuleTest {
@Mock
@Bind
TokenClient tokenClient;
@Test
public void testHelloWorldClient() {
MockitoAnnotations.openMocks(this);
Module testMainModule = Modules.override(new MainModule())
.with(BoundFieldModule.of(this)
...
}
}
Notes:
TestMainModule
How it works:
BoundFieldModule.of(this)
creates a test module on the fly, using all of the fields in the test class which are annotated with @Bind
. Since tokenClient
is also a mock instance, the binding in the module will contain the mock.Modules.override
will overlay the BoundFieldModule
over MainModule
. Concretely,
TokenClient
, since it gives precedence to the binding in the BoundFieldModule
; andHttpClientPool
, since this is only bound in MainModule
.I'm not sure what the point is of getting the testMainModule
instance. If we wanted to get an instance of HttpClientPool
from the test module, we could do it like this:
class MainModuleTest {
@Mock
@Bind
TokenClient tokenClient;
@Inject
HttpClientPool httpClientPool;
@Test
public void testHelloWorldClient() {
MockitoAnnotations.openMocks(this);
injector = Guice.createInjector(
Modules.override(new MainModule()).with(BoundFieldModule.of(this))
)
injector.injectMembers(this)
httpClientPool.doStuff()
}
}
In this case, the injector uses the overridden module to inject an instance of HttpClientPoolImpl
into the httpClientPool
field.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With