public interface Template {
foo();
}
public class SomeTemplate implements Template {
@Inject
public SomeTemplate (Session session){
this.session = session;
}
public foo() {
// do something
}
}
// Module with bindings
public class TemplateModule extends AbstractModule {
@Override
protected void configure() {
bind(Session.class).toInstance(session);
bind(Template.class).to(SomeTemplate.class);
}
public static class Builder {
private Session session;
public TemplateModule buildModule() {
return new TemplateModule(session);
}
public Builder withSession(String session) {
this.session = session;
return this;
}
}
}
// JUnt 4.4 test
public class TemplateTest {
@Inject
Template template; // doesn't inject!
@BeforeClass
public static void init() throws Exception {
injector = Guice.createInjector(new
TemplateModule.Builder().withSession(new Session()));
// template= injector.getInstance(Template.class); // template is
initialized if this is uncommented
}
@Test
public void testFoo() {
template.foo(); // NullPointerException
}
}
What is wrong with the above code? Why doesn't @Inject automatically
inject the template instance variable? It seems redundant (and
limited) that I have to yet again use Injector.getInstance, each time
I need to access the template object. I'm sure doing something wrong
here ...
new AbstractModule() { public void configure() { requestInjection(this); } }
then Guice will know to process @Inject methods/variables within
TemplateTest too.
Sam
> --
> You received this message because you are subscribed to the Google Groups "google-guice" group.
> To post to this group, send email to google...@googlegroups.com.
> To unsubscribe from this group, send email to google-guice...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/google-guice?hl=en.
>
>
1) TemplateModule binds an implementing class
bind(Template.class).to(SomeTemplate.class);
2) created a TemplateModule and initialized it in the Test Class
injector = Guice.createInjector(new
TemplateModule.Builder().withSession(new Session()).buildModule());
3) The same Test class has a @inject Template template
Why is it not injected?
From your answer, it looks like I have to create one module per class
where @inject is present. That seems incorrect to me.
Because Guice is not in charge of creating your test class instances.
So you either have to explicitly ask it to inject for you, get a
reference yourself by using the injector, or use something like
AtUnit: http://code.google.com/p/atunit/wiki/SupportedContainers
Eelco
AtUnit looks cool; will check it out. Meanwhile, I added this in the
@BeforeClass in my unit test
injector = Guice.createInjector(new
TemplateModule.Builder().withSession(new Session()).buildModule(),
new AbstractModule() {
@Override
public void configure() {
requestInjection(this);
}});
On running the debugger, I can see that template is initialized after
createInjector. However, my test (@Test) method still has a null
reference.
Strange, right? Am I missing something?
Got it. Wasn't quite intuitive in the beginning but it seems like a
"Module" is analogous to a <bean-id> in spring.
So if you have 25
beans that refers a single bean, "foo", you have a reference for foo
in all those beans. However, to reduce the boilerplate code, Spring
provides autowire(byType or byName). Is there a similar feature in
Guice.
This doesn't work because requestInjection(this) requests injection of
your anonymous module
and because @BeforeClass can only be used on a static method, so there
is no 'this' for your unit test.
I think adding a method with @Before and then
requestInjection(YourTest.this) should work. Or you could use
requestStaticInjection instead. Or, what I would do frankly, don't
bother and just get your instance from the injector when you need it.
Eelco
Dhanji:
I still don't understand how autowire is "by default" in Guice. In the
example I mentioned, I have to create n modules for each Class
referencing template variable. Agreed, the following code
new AbstractModule() {
@Override
public void configure() {
requestStaticInjection (this);
}});
would inject the reference in the static instance, but that means I
have to write the same boilerplate code for every test, ie, every
class that has @Inject Template template.
@Inject is a Guice annotation and I expect it to be smart to figure
out (autowire) the binding.
As I understand now, this is not the case.
Thanks Eelco, I figured the anonymous inner class accessing an object
reference, and while fixing it, your suggestion of using
requestStaticInjection solves my problem.
Dhanji:
I still don't understand how autowire is "by default" in Guice. In the
example I mentioned, I have to create n modules for each Class
referencing template variable. Agreed, the following code
requestStaticInjection (this);
new AbstractModule() {
@Override
public void configure() {
}});
would inject the reference in the static instance, but that means I
have to write the same boilerplate code for every test, ie, every
class that has @Inject Template template.
injector.injectMembers(this);
in your test class right after acquiring the injector instance (before
the commented template = injector.getInstance(...) line). This will
fullfil the injection requests in the test itself. I use a base test
class that does the equivalent for injecting loggers, Sessions, etc..,
so there shouldn't be a ton of boilerplate.
Is using an injector in tests common practice? I would have thought
that hand wiring would be more popular.
--
David
blog: http://www.traceback.org
twitter: http://twitter.com/dstanek
On Mar 3, 10:37 am, David Stanek <dsta...@dstanek.com> wrote: