TestNG
supports two different kinds of dependency injection: native (performed by
TestNG itself) and external (performed by a dependency injection framework such
as Guice).
TestNG
lets you declare additional parameters in your methods. When this happens,
TestNG will automatically fill these parameters with the right value.
Dependency injection can be used in the following places:
- Any @Before method or @Test method can declare a parameter of type ITestContext.
- Any @AfterMethod method can declare a parameter of type ITestResult, which will reflect the result of the test method that was just run.
- Any @Before and @After methods can declare a parameter of type XmlTest, which contain the current <test> tag.
- Any @BeforeMethod (and @AfterMethod) can declare a parameter of type java.lang.reflect.Method. This parameter will receive the test method that will be called once this @BeforeMethod finishes (or after the method as run for @AfterMethod).
- Any @BeforeMethod can declare a parameter of type Object[]. This parameter will receive the list of parameters that are about to be fed to the upcoming test method, which could be either injected by TestNG, such as java.lang.reflect.Method or come from a @DataProvider.
- Any @DataProvider can declare a parameter of type ITestContext or java.lang.reflect.Method. The latter parameter will receive the test method that is about to be invoked.
You can
turn off injection with the @NoInjection annotation:
public class NoInjectionTest {
|
|
|
@DataProvider(name = "provider")
|
|
public Object[][] provide() throws Exception {
|
return new Object[][] { {
CC.class.getMethod("f") } };
|
|
}
|
|
|
@Test(dataProvider = "provider")
|
public void withoutInjection(@NoInjection Method m) {
|
|
Assert.assertEquals(m.getName(),
"f");
|
}
|
|
|
@Test(dataProvider = "provider")
|
|
public void withInjection(Method m) {
|
Assert.assertEquals(m.getName(),
"withInjection");
|
|
}
|
}
|
If you
use Guice, TestNG gives you an easy way to inject your test objects with a
Guice module:
@Guice(modules = GuiceExampleModule.class)
|
|
public class GuiceTest extends SimpleBaseTest {
|
|
|
@Inject
|
ISingleton m_singleton;
|
|
|
@Test
|
|
public void singletonShouldWork() {
|
m_singleton.doSomething();
|
|
}
|
|
|
}
|
In this
example, GuiceExampleModule is
expected to bind the interface ISingleton to some concrete class:
public class GuiceExampleModule implements Module {
|
|
|
@Override
|
|
public void configure(Binder binder) {
|
binder.bind(ISingleton.class).to(ExampleSingleton.class).in(Singleton.class);
|
|
}
|
|
|
}
|
If you
need more flexibility in specifying which modules should be used to instantiate
your test classes, you can specify a module factory:
@Guice(moduleFactory = ModuleFactory.class)
|
|
public class GuiceModuleFactoryTest {
|
|
|
@Inject
|
ISingleton m_singleton;
|
|
|
@Test
|
|
public void singletonShouldWork() {
|
m_singleton.doSomething();
|
|
}
|
}
|
The
module factory needs to implement the interface IModuleFactory:
public interface IModuleFactory {
|
|
/**
|
* @param context The current test context
|
|
* @param testClass The test class
|
*
|
|
* @return The Guice module that should be used to
get an instance of this
|
* test class.
|
|
*/
|
Module createModule(ITestContext context, Class<?>
testClass);
|
|
}
|
Your
factory will be passed an instance of the test context and the test class that
TestNG needs to instantiate. Your createModule method should return a Guice
Module that will know how to instantiate this test class. You can use the test
context to find out more information about your environment, such as parameters
specified in testng.xml, etc...
I really liked your blog post.Much thanks again. Awesome.
ReplyDeleteonline training in java
online training on java