Injecting named Guice singleton
Solution 1
Very odd. Guice should complain if it can't find a Named
binding that it's injecting. I'm a bit confused by your test, though. I don't know what injector.inject
does. Do you mean injectMembers
? It might make more sense to actually get an instance of your POJO and make sure that it's working the way you expect. Maybe something like:
public class FizzTest {
public static class MyModule extends AbstractModule {
@Override
protected void configure() {
}
@Provides
@Singleton
@Named("Special-Fizz")
public Fizz providesFizz() {
return new Fizz(true);
}
}
public static class Fizz {
boolean special = false;
public Fizz() {}
public Fizz(boolean special) {
this.special = special;
}
}
public static class MyPOJO {
@Inject @Named("Special-Fizz")
private Fizz fizz;
@Inject
private Fizz otherFizz;
}
@Test
public void test() {
MyModule mod = new MyModule();
Injector injector = Guice.createInjector(mod);
MyPOJO pojo = injector.getInstance(MyPOJO.class);
assertTrue(pojo.fizz.special);
assertTrue(!pojo.otherFizz.special);
}
}
Solution 2
Guice sees the @Provides
method and happily uses that to inject the Fizz
. If you want to have a special instance of Fizz
, you can drop the annotations from the providesFizz()
method and instead bind with
bind(Fizz.class)
.annotatedWith(Names.named("Special-Fizz")
.toInstance(providesFizz());
This way, you tell Guice exactly which Fizz
to use as the "Special-Fizz", while still letting it inject Fizz
"normally" otherwise.
Disclaimer: I haven't actually tried a setup like yours, but I have used one similar. Let me know if it works or not.
IAmYourFaja
my father is a principal at burgoyne intnl and got me this job programming lisp and development. I aspire to unittesting with a concentration in mobile platforms.
Updated on June 17, 2022Comments
-
IAmYourFaja almost 2 years
I have a simple POJO:
public class MyPOJO { @Inject private Fizz fizz; private Buzz buzz; // rest of class omitted for brevity }
I would like to configure my Guice module such that there are two types of
Fizz
es that it injects:- A special, globally-singleton
Fizz
instance; and - Other (non-special)
Fizz
instances
I want
MyPOJO
to be injected with the special/singleton instance. So I modified my code:public class MyPOJO { @Inject @Named("Special-Fizz") private Fizz fizz; private Buzz buzz; // rest of class omitted for brevity }
Then in my module:
public class MyModule extends AbstractModule { @Override public void configure() { bind(Fizz.class).annotatedWith( Names.named("Special-Fizz")) .to(Fizz.class); // Other bindings here... } @Provides @Singleton private Fizz providesFizz() { return new Fizz(true, "Special", 12.0); } }
But when I try to unit test (JUnit 4.10) this:
public class MyTest { @Named("Special-Fizz") private Fizz specialFizz; @Test public void usingNamedShouldInjectSpecialFizz() { MyModule mod = new MyModule(); Injector injector = Guice.createInjector(mod); specialFizz = injector.getInstance(Fizz.class); Assert.assertTrue(specialFizz != null); } }
This passes. So far, so good. But then if I change the name of the
specialFizz
field:@Named("Special-Fuzz-This-Shouldnt-Work") private Fizz specialFizz;
And re-run the test, it still passes. Why?!? Where am I going astray here? Thanks in advance.
- A special, globally-singleton
-
IAmYourFaja about 11 yearsThanks @Bradley T. Hughes (+1) - however your suggestion doesn't change anything. The unit test still passes, regardless of what you name the
Fizz
. You mentioned something that I thought was interesting. You said "I haven't actually tried a setup like yours...", however, from your answer I deduce that you seem to be fairly comfortable using Guice. So it makes me wonder: Is this a bizarre setup that I'm using? I thought the point of Guice was to use Classes and Annotations together to pinpoint exactly what type/config you want injected... -
IAmYourFaja about 11 years...so am I doing something here that is out of the ordinary? If so, why?!? Where am I misunderstanding the normal usage of Guice? Thanks again!
-
IAmYourFaja about 11 yearsThanks @condit (+1) - that was an error on my part in typing up this question. I've edited my original question to show that I'm actually calling
injector.getInstance
, notinjector.inject
. Does that change anything for you? IsgetInstance
not correct for me to be using here? If so, why, and what is? Thanks again! -
condit about 11 yearsIn your test you're asking the injector for an instance of
Fizz
which it will always be able to provide you (because of your@Provides
method). I think you want to get an instance ofMyPOJO
instead. Note that theFizz
you're getting is unrelated to theFizz
member of the test. So changing the@Named
will have no effect in this case. -
IAmYourFaja about 11 yearsYou nailed it. I just asked it to inject a
MyPOJO
and it correctly injected it'sFizz
property with my special fizz. Mystery solved - just a poorly implemented test method. Thanks again! -
Bradley T. Hughes about 11 yearsI don't think it's a bizarre setup. And to be honest, I've not used Guice that much, so I'm certainly no expert. The difference is that the code I am working on uses the same annotation to inject two different types (one single instance of each).