Reputation: 23
I have a maven project javaruntime
and a maven project androidruntime
which depends on the javaruntime
project.
Each of the projects has a Guice-Module binding some classes to Interfaces.
In the javaruntime
is an Interface IElementFactory
and a Class C
which gets the IElementFactory
by constructor injection:
public class C {
@Inject
public C(IElementFactory factory, ...(other interfaces)...) {...}
// ...
}
The concrete Implementation for the IElementFactory
is in the androidruntime
project and called AndroidElementFactory
. All implementations of the other interfaces are within the javaruntime
.
In the javaruntime
I have JUnit-tests which should use a MockElementFactory
because it does not know the androidruntime
.
If I bind the IElementFactrory
to the AndroidElementFactory
only in the androidruntime
Module, the Tests fail of course, because no implementation is bound for that interface within the javaruntime
Module/project.
If I then bind the MockElementFactory
in the javaruntime
Module the tests are fine, but then I cannot compile the androidruntime
because the IElementFactory is already bound to the MockElementFactory
and overriding a binding is bad and not reommended in Guice.
But how can I accomplish that the Mock is used for the test and in the android-project it is still possible to bind the correct implementation?
Upvotes: 2
Views: 2491
Reputation: 127771
First of all, in fact you don't want to do that. When you're unit testing your class, especially with mocks, you shouldn't use Guice. Instead you should instantiate your class directly, providing all its dependencies to it. Since you're writing unit test this should not be a problem, since all its dependencies in the test should be trivial or be mocked.
But if you really want to do what you intend to do, you have to split your program into several modules. For simplicity, let them be MainModule
, MockModule
and AndroidModule
. In MainModule
you configure all your bindings except for IElementFactory
. It can look like this:
public class MainModule extends AbstractModule {
@Override
protected void configure() {
// Require presence of IElementFactory
requireBinding(IElementFactory.class);
// Bind all other dependencies
...
}
}
And in your MockModule
and AndroidModule
you bind corresponding implementations of IElementFactory
.
Then in your tests you create your injector like this:
Injector injector = Guice.createInjector(new MainModule(), new MockModule());
and in android project you create it like this:
Injector injector = Guice.createInjector(new MainModule(), new AndroidModule());
If you cannot do this because injector instantiation is hardcoded, then you should really consider refactoring your program because it is not how Guice projects are structured, especially wrt. unit tests. I cannot say more because you haven't explained exact structure of your program.
Upvotes: 6