On 27 Oct 2011, at 21:12, Jeff wrote: > The classes containing the injected fields are TestNG test classes. I am > creating the Injector using the ServiceLoader mechanism within a class that > implements org.testng.ISuiteListener. TestNG automatically picks up and runs > the onStart() method before doing anything else and I call createInjector() > there. > > Though, I think I just realized my problem (besides trying to learn/use Guice > from within another framework I'm also just learning). > > The key bit I had not grasped previously was that for Guice/@Inject to work, > object instantiation must be done directly by Guice (Injector.getInstance()), > at least for the root node of the object graph (I think). > > Since TestNG instantiates classes without Guice by default, it was just > creating normal instances and the @Inject annotations weren't getting > processed. > > TestNG does support Guice via @Test(guiceModule = MyModule.class) annotation, > but I wanted to avoid the need to put this on EVERY test class and thought I > could insert my Modules/Providers and enable my custom bindings to work > globally. > > I'm still playing with my code, but I feel like I'm on the right track. Can > anyone confirm or help me understand if there is a different way?
Yes, either the root of the object graph needs to be instantiated by Guice or you need to use injectMembers(...) to inject an existing instance (in which case you can't use constructor injection in that particular class). Of course one benefit of putting @Test(guiceModule=...) on each test class (or @Guice in the latest version: http://testng.org/doc/documentation-main.html#guice-dependency-injection) is that it documents that you're using dependency injection for that test, and with modern IDEs it's not too hard to add this automatically or use a template. Also note the latest release of TestNG supports module factories so you could use the same factory across all your tests: http://testng.org/javadocs/org/testng/IModuleFactory.html > Thanks!! > > On Thu, Oct 27, 2011 at 5:40 AM, Stuart McCulloch <[email protected]> wrote: > On 27 Oct 2011, at 06:14, Jeff wrote: > >> I want to do something like: >> @Inject @Named("conf") >> Properties config; >> >> @Inject @Named("lang") >> Properties language; >> Where these objects are singletons initialized once at runtime with >> environment-specific information. >> >> I've tried various things and none result in my Provider or @Provides >> methods getting called. Here is a trimmed down version of my code using a >> Provider class: >> >> MyModule.java: >> public class SeleniumInjectionModule extends AbstractModule { >> @Override >> protected void configure() { >> >> bind(Properties.class).annotatedWith(Names.named("conf")).toProvider(ConfigProvider.class); >> >> bind(Properties.class).annotatedWith(Names.named("lang")).toProvider(LanguageProvider.class); >> } >> } >> ConfigProvider.java: >> @Singleton >> public class ConfigProvider implements Provider<Properties> { >> private final Properties config = new Properties(); >> >> public ConfigProvider() { >> //Load properties file based on 'config' system property value set in >> Maven profile >> ... >> config.load(...); >> ... >> } >> @Override >> public Properties get() { >> return config; >> } >> } >> >> LanguageProvider.java: >> @Singleton >> public class LanguageProvider implements Provider<Properties> { >> private final Properties lang = new Properties(); >> >> public LanguageProvider() { >> //Load properties file based on 'language' system property value set in >> Maven profile >> ... >> lang.load(...); >> ... >> } >> @Override >> public Properties get() { >> return lang; >> } >> } >> In my Global Init code: >> Guice.createInjector(new MyModule()); >> >> What am I missing? > > Where's the class containing the injected config/language fields mentioned in > the start of this email? > > Assuming that class is called Foo then you need to use > injector.getInstance(Foo.class) - or injector.injectMembers(myFoo) if you > already have an instance of Foo - to start the injection process and inject > those fields. Note that you don't need to do this for everything, just the > class at the beginning of the injection graph to kick things off. > >> -- >> Jeff Vincent >> [email protected] >> See my LinkedIn profile at: >> http://www.linkedin.com/in/rjeffreyvincent >> I ♥ DropBox !! >> >> >> -- >> You received this message because you are subscribed to the Google Groups >> "google-guice" group. >> To post to this group, send email to [email protected]. >> To unsubscribe from this group, send email to >> [email protected]. >> For more options, visit this group at >> http://groups.google.com/group/google-guice?hl=en. > > > -- > You received this message because you are subscribed to the Google Groups > "google-guice" group. > To post to this group, send email to [email protected]. > To unsubscribe from this group, send email to > [email protected]. > For more options, visit this group at > http://groups.google.com/group/google-guice?hl=en. > > > > -- > Jeff Vincent > [email protected] > See my LinkedIn profile at: > http://www.linkedin.com/in/rjeffreyvincent > I ♥ DropBox !! > > > -- > You received this message because you are subscribed to the Google Groups > "google-guice" group. > To post to this group, send email to [email protected]. > To unsubscribe from this group, send email to > [email protected]. > For more options, visit this group at > http://groups.google.com/group/google-guice?hl=en. -- You received this message because you are subscribed to the Google Groups "google-guice" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/google-guice?hl=en.
