A binding is an object that corresponds to an entry in the Guice map. You add new entries into the Guice map by creating bindings.
Interface Module A module contributes configuration information, typically interface bindings, which will be used to create an Injector . A Guice-based application is ultimately composed of little more than a set of Module s and some bootstrapping code.
This might not be the answer you're looking for, but if you're writing unit tests, you probably shouldn't be using an injector and rather be injecting mock or fake objects by hand.
On the other hand, if you really want to replace a single binding, you could use Modules.override(..)
:
public class ProductionModule implements Module {
public void configure(Binder binder) {
binder.bind(InterfaceA.class).to(ConcreteA.class);
binder.bind(InterfaceB.class).to(ConcreteB.class);
binder.bind(InterfaceC.class).to(ConcreteC.class);
}
}
public class TestModule implements Module {
public void configure(Binder binder) {
binder.bind(InterfaceC.class).to(MockC.class);
}
}
Guice.createInjector(Modules.override(new ProductionModule()).with(new TestModule()));
See details here.
But as the javadoc for Modules.overrides(..)
recommends, you should design your modules in such a way that you don't need to override bindings. In the example you gave, you could accomplish that by moving the binding of InterfaceC
to a separate module.
Why not to use inheritance? You can override your specific bindings in overrideMe
method, leaving shared implementations in configure
method.
public class DevModule implements Module {
public void configure(Binder binder) {
binder.bind(InterfaceA.class).to(TestDevImplA.class);
overrideMe(binder);
}
protected void overrideMe(Binder binder){
binder.bind(InterfaceC.class).to(ConcreteC.class);
}
};
public class TestModule extends DevModule {
@Override
public void overrideMe(Binder binder) {
binder.bind(InterfaceC.class).to(MockC.class);
}
}
And finally create your injector this way:
Guice.createInjector(new TestModule());
If you don't want to change your production module and if you have a default maven-like project structure like
src/test/java/...
src/main/java/...
You can just create a new class ConcreteC
in your test directory using the same package as for your original class. Guice will then bind InterfaceC
to ConcreteC
from your test directory whereas all other interfaces will be bound to your production classes.
You want to use Juckito where you can declare your custom configuration for each test class.
@RunWith(JukitoRunner.class)
class LogicTest {
public static class Module extends JukitoModule {
@Override
protected void configureTest() {
bind(InterfaceC.class).to(MockC.class);
}
}
@Inject
private InterfaceC logic;
@Test
public testLogicUsingMock() {
logic.foo();
}
}
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