TestNG has allowed users to control the instantation of their objects for a while now (around 2007).
This is enabled by the IObjectFactory interface:
public interface IObjectFactory extends Serializable { Object newInstance(Constructor constructor, Object... params); }
Implement this interface, let TestNG know about your implementation and whenever TestNG needs to instantiate a test class, it will call the newInstance method of your object factory. This allows for a lot of flexibility, and interestingly, this interface appeared in the TestNG distribution long before Dependency Injection became as popular as it is today.
IObjectFactory has been very useful to TestNG users throughout the years, but the emergence of Dependency Injection has made its existence even more important. More and more TestNG users want to inject their test classes with DI frameworks, and over the past few months, I have noticed a sharp increase in Guice users.
IObjectFactory obviously works great with Guice (and Hani and I documented this extensively in our book) but the increased number of questions on the mailing-list prompted me to wonder if I couldn’t make this easier on Guice users.
As it turns out, the answer is yes.
Meet my little new friend, the guiceModule attribute:
@Test(guiceModule = GuiceExampleModule.class) public class GuiceTest { @Inject ISingleton m_singleton; @Test public void singletonShouldWork() { m_singleton.doSomething(); } }
And that’s it! No need for IObjectFactory or modifying your build files, everything you need is contained in this new guiceModule attribute of the @Test annotation.
Obviously, this module needs to create the necessary bindings for the @Inject annotation to work properly, for example:
public class GuiceExampleModule implements Module { @Override public void configure(Binder binder) { binder.bind(ISingleton.class).to(ExampleSingleton.class) .in(Singleton.class); } }
With this new attribute, using TestNG with Guice has never been easier. Try it for yourself, download the beta and tell us what you think!
#1 by Georg on December 11, 2010 - 1:40 am
Great. Simple and very usable – but I guess it should be guicemodules instead of guiceModule, because sometimes you have more than one configuration modules.
#2 by Gunnar on December 11, 2010 - 2:20 pm
Hi Cedric,
I like the itention behind the change – making Guice easier to use in tests. But I see some issues with its current implementation:
* You are introducing one special concept/technology – Guice – into the otherwise very generically usable TestNG. I think these things shouldn’t be mixed up, in especially this adds conceptual complexity for all those people using TestNG but not Guice.
* Currently any classes are allowed as annotation value for “guiceModule”, but actually only classes implementing Module make sense here. So one rather should have something like
Class[] guiceModules() default {};
Obviously this can’t be done in @Test itself. Therefore I think it would be better to have a separate annotation such @GuiceModules which can be specified next to @Test to define the modules to use.
Alternatively one could think of an annotation @GuiceTest which resembles @Test but adds the new module attribute.
Both ways any non-Guice users could work with @Test as before without stumbling upon a new annotation attribute which doesn’t make sense to them and any Guice users could specify modules for their tests in a safe way.
Gunnar
#3 by Gunnar on December 11, 2010 - 2:29 pm
Just saw some characters from my comment were swallowed. It should say
Class<? extends Module>[] guiceModules() default {};
(So in case this doesn’t work again, what I mean is to restrict the allowed classes to sub-types of Module (“? extends Module”)).
#4 by Ruslan Zenin on December 12, 2010 - 5:30 am
Cedric,
Great addition to TestNG! I happen to use Guice extensively and TestNG as well… this will definitely help simplify things!
Having said that, I agree with Gunnar’s point on having “guiceModules” moving out of @Test annotation into a separate Guice specific annotation like @GuiceModules. This will make it cleaner.
Please give it a thought!
regards,
Ruslan
#5 by Cedric on December 12, 2010 - 8:07 am
Gunnar: I agree, the final version will do what you suggest. Stay tuned!
#6 by Gunnar on December 12, 2010 - 2:17 pm
That’s great news, I’m looking forward to the new draft.
#7 by Frederic Fortin on December 21, 2010 - 6:37 am
Hi,
I’m fairly new to both TestNG and Guice but from my understanding of DI, the test classes should’nt contain any annotation binding them to the module. To me this would be like creating a dependency on a factory. I might be missing something here but how would a test class be reusable in multiple Guice modules?
Perhaps you could make a module referencable from the xml files just like the object factory is so that a single test class can be used in multiple modules without having to change annotations with classes themselves.
Please let me know if this does not make any sense. I’m on a learning road
Pingback: Announcing TestNG 6.0 « Otaku, Cedric's blog
#8 by Logan on August 1, 2011 - 6:54 am
I’ve been using this IObjectFactory for years and indeed, it is very useful to TestNG until now.
I’ve also used guiceModule attribute of the @Test annotation in order to modify my build files.
Thanks for Sharing
#9 by Luicer@Nikenya.com on October 13, 2011 - 9:08 pm
Hello! I like this informative ideas about TestNG since we are also looking forward to have our ‘roll in your own’ dependency framework for test classes using Weld, but this is really cool as well. Thanks for your frame work!
#10 by Lynkez@Nikenya Domain Names on November 7, 2011 - 8:52 pm
I am a fan of IObjectFactory on Test NG and glad to recieve the good news about GuicerModule. Thumbs up!