I have the following code:
import static org.hamcrest.CoreMatchers.*;
import static org.hamcrest.MatcherAssert.*;
import com.google.inject.*;
import org.junit.jupiter.api.*;
public class GuiceTest {
public static void main(String[] args) {
new GuiceTest().test();
}
@Test
public void test() {
Injector injector = Guice.createInjector();
MainObject obj1 = injector.getInstance(MainObject.class);
MainObject obj2 = injector.getInstance(MainObject.class);
// Ensure two distinct objects.
assertThat(obj1, is(not(sameInstance(obj2))));
Dependency dep1 = obj1.getDependency();
Dependency dep2 = obj2.getDependency();
for (int i = 0; i < 10; i++) {
// Ensure only one dependency instance per distinct object
assertThat(dep1, is(sameInstance(obj1.getDependency())));
assertThat(dep2, is(sameInstance(obj2.getDependency())));
}
// Ensure each object has its own dependency.
assertThat(dep1, is(not(sameInstance(dep2)))); // fails
}
static class ChildModule extends PrivateModule {
@Override
protected void configure() {
}
}
static class MainObject {
private final Injector injector;
@Inject
MainObject(Injector injector) {
this.injector = injector.createChildInjector(new ChildModule());
}
Dependency getDependency() {
return injector.getInstance(Dependency.class);
}
}
@Singleton
static class Dependency {
}
}
The goal is to have one (and only one) Dependency
per MainObject
. This is why I declared it @Singleton
and called it from the child injector.
It looks like despite I use a child injector, the singleton is registered in the parent one.
What am I doing wrong?
Notes:
- This is only a subset of the full use case. The full use case contains 40+ dependencies.
- Each dependency is optional, so I thought about keeping them in the injector and accessing them through the injector. Their existence is checked with
injector.getExistingBinding(Key.of(Class))
. - The module may not define the dependencies, the dependencies need to be implemented as "implicit" (so that I can use them easily without having to define them in the module).