1.-依賴注入
TestNG支持兩種不同類型的依賴項注入:本機(由TestNG本身執行)和外部(由諸如Guice的依賴項注入框架執行)。
1.1-本機依賴項注入
TestNG允許您在方法中聲明其他參數。發生這種情況時,TestNG將自動用正確的值填充這些參數。依賴注入可以在以下地方使用:
任何@Before方法或@Test方法都可以聲明ITestContext類型的參數。
任何@AfterMethod方法都可以聲明ITestResult類型的參數,該參數將反映剛剛運行的測試方法的結果。
任何@Before和@After方法(@BeforeSuite和@AfterSuite除外)都可以聲明XmlTest類型的參數,該參數包含當前的<test>標記。
任何@BeforeMethod(和@AfterMethod)都可以聲明java.lang.reflect.Method類型的參數 。此參數將接收此@BeforeMethod完成之后(或在為@AfterMethod運行的方法之后)將調用的測試方法。
任何@BeforeMethod都可以聲明Object []類型的參數。此參數將接收即將饋入即將到來的測試方法的參數列表,該參數列表可以由TestNG注入,例如java.lang.reflect.Method或來自@DataProvider。
任何@DataProvider都可以聲明ITestContext或java.lang.reflect.Method類型的參數 。后一個參數將接收將要調用的測試方法。
您可以使用@NoInjection批注關閉注入:
/** * @author 北京-宏哥 * * Java自動化測試框架-09 - TestNG之 依賴注入篇 * * 2019年11月8日 */ 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"); } }
下表總結了可以為各種TestNG注釋本地注入的參數類型:
Annotation | ITestContext | XmlTest | Method | Object[] | ITestResult |
---|---|---|---|---|---|
BeforeSuite | Yes | No | No | No | No |
BeforeTest | Yes | Yes | No | No | No |
BeforeGroups | Yes | Yes | No | No | No |
BeforeClass | Yes | Yes | No | No | No |
BeforeMethod | Yes | Yes | Yes | Yes | Yes |
Test | Yes | No | No | No | No |
DataProvider | Yes | No | Yes | No | No |
AfterMethod | Yes | Yes | Yes | Yes | Yes |
AfterClass | Yes | Yes | No | No | No |
AfterGroups | Yes | Yes | No | No | No |
AfterTest | Yes | Yes | No | No | No |
AfterSuite | Yes | No | No | No | No |
1.2-Guice依賴注入
如果您使用Guice,TestNG為您提供了一種簡單的方法,即可通過Guice模塊注入測試對象:
/** * @author 北京-宏哥 * * Java自動化測試框架-09 - TestNG之 依賴注入篇 * * 2019年11月8日 */ @Guice(modules = GuiceExampleModule.class) public class GuiceTest extends SimpleBaseTest { @Inject ISingleton m_singleton; @Test public void singletonShouldWork() { m_singleton.doSomething(); } }
在此示例中,預計GuiceExampleModule會將接口ISingleton綁定到一些具體的類:
/** * @author 北京-宏哥 * * Java自動化測試框架-09 - TestNG之 依賴注入篇 * * 2019年11月8日 */ public class GuiceExampleModule implements Module { @Override public void configure(Binder binder) { binder.bind(ISingleton.class).to(ExampleSingleton.class).in(Singleton.class); } }
如果需要更大的靈活性來指定應使用哪些模塊實例化測試類,則可以指定模塊工廠:
/** * @author 北京-宏哥 * * Java自動化測試框架-09 - TestNG之 依賴注入篇 * * 2019年11月8日 */ @Guice(moduleFactory = ModuleFactory.class) public class GuiceModuleFactoryTest { @Inject ISingleton m_singleton; @Test public void singletonShouldWork() { m_singleton.doSomething(); } }
模塊工廠需要實現接口IModuleFactory:
/** * @author 北京-宏哥 * * Java自動化測試框架-09 - TestNG之 依賴注入篇 * * 2019年11月8日 */ 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); }
您的工廠將被傳遞TestNG需要實例化的測試上下文和測試類的實例。您的createModule方法應返回一個Guice模塊,它將知道如何實例化此測試類。您可以使用測試上下文來查找有關您的環境的更多信息,例如在testng.xml中指定的參數等。通過父模塊和guice-stage套件參數,您將獲得更大的靈活性和Guice功能。 guice-stage可讓您選擇用於創建父注射器的Stage。默認值是DEVELOPMENT。其他允許的值為PRODUCTION和TOOL。這是在test.xml文件中定義父模塊的方法:
<suite parent-module="com.example.SuiteParenModule" guice-stage="PRODUCTION"> </suite>
對於給定的套件,TestNG將只創建一次此模塊。還將使用該模塊獲取特定於測試的Guice模塊和模塊工廠的實例,然后將為每個測試類創建子注入器。通過這種方法,您可以在父模塊中聲明所有公共綁定,也可以在模塊和模塊工廠中注入在父模塊中聲明的綁定。這是此功能的示例:
/** * @author 北京-宏哥 * * Java自動化測試框架-09 - TestNG之 依賴注入篇 * * 2019年11月8日 */ package com.example; public class ParentModule extends AbstractModule { @Override protected void conigure() { bind(MyService.class).toProvider(MyServiceProvider.class); bind(MyContext.class).to(MyContextImpl.class).in(Singleton.class); } }
/** * @author 北京-宏哥 * * Java自動化測試框架-09 - TestNG之 依賴注入篇 * * 2019年11月8日 */ package com.example; public class TestModule extends AbstractModule { private final MyContext myContext; @Inject TestModule(MyContext myContext) { this.myContext = myContext } @Override protected void configure() { bind(MySession.class).toInstance(myContext.getSession()); } }
<suite parent-module="com.example.ParentModule"> </suite>
/** * @author 北京-宏哥 * * Java自動化測試框架-09 - TestNG之 依賴注入篇 * * 2019年11月8日 */ package com.example; @Test @Guice(modules = TestModule.class) public class TestClass { @Inject MyService myService; @Inject MySession mySession; public void testServiceWithSession() { myService.serve(mySession); } }
如您所見,ParentModule為MyService和MyContext類聲明了綁定。然后使用構造函數注入將MyContext注入到TestModule類中,該類也聲明對MySession的綁定。然后將測試XML文件中的parent-module設置為ParentModule類,這將啟用在TestModule中的注入。稍后在TestClass中,您會看到兩次注入:* MyService-綁定取自ParentModule * MySession-綁定取自TestModule此配置可確保您使用同一會話實例運行該套件中的所有測試,MyContextImpl對象每個套件僅創建一次,這使您可以為套件中的所有測試配置通用環境狀態。
2.-偵聽方法調用
每當TestNG即將調用測試(用@Test注釋)或配置(用@Before或@After注釋中的任何一個注釋)方法時 ,偵聽器IInvokedMethodListener都會通知您。您需要實現以下接口:
/** * @author 北京-宏哥 * * Java自動化測試框架-09 - TestNG之 依賴注入篇 * * 2019年11月8日 */ public interface IInvokedMethodListener extends ITestNGListener { void beforeInvocation(IInvokedMethod method, ITestResult testResult); void afterInvocation(IInvokedMethod method, ITestResult testResult); }
並將其聲明為偵聽器,如有關TestNG偵聽器的部分所述。
3.-覆蓋測試方法
TestNG允許您重寫並可能跳過測試方法的調用。一個有用的例子是,如果您需要使用特定的安全管理器來測試方法。您可以通過提供實現IHookable的偵聽器來實現此目的。
這是JAAS的示例:
/** * @author 北京-宏哥 * * Java自動化測試框架-09 - TestNG之 依賴注入篇 * * 2019年11月8日 */ public class MyHook implements IHookable { public void run(final IHookCallBack icb, ITestResult testResult) { // Preferably initialized in a @Configuration method mySubject = authenticateWithJAAs(); Subject.doAs(mySubject, new PrivilegedExceptionAction() { public Object run() { icb.callback(testResult); } }; } }
4.-變更套件(或)測試
有時,您可能只需要在運行時更改套件xml中的套件(或)測試標簽,而不必更改套件文件的內容。
一個典型的例子就是嘗試利用現有的套件文件,並嘗試使用它在“被測應用程序”上模擬負載測試。至少您最終將多次復制<test>標記的內容,並創建一個新的套件xml文件並使用。但這似乎並沒有太大的規模。
TestNG允許您在運行時通過偵聽器更改套件xml文件中的套件(或)測試標簽。您可以通過提供實現IAlterSuiteListener的偵聽器來實現此目的。請參考“ 監聽器”部分以了解監聽器。
這是一個示例,顯示套件名稱在運行時如何更改:
/** * @author 北京-宏哥 * * Java自動化測試框架-09 - TestNG之 依賴注入篇 * * 2019年11月8日 */ public class AlterSuiteNameListener implements IAlterSuiteListener { @Override public void alter(List<XmlSuite> suites) { XmlSuite suite = suites.get(0); suite.setName(getClass().getSimpleName()); } }
只能通過以下兩種方式之一添加此偵聽器:
通過套件xml文件中的<listeners>標記。
通過服務加載程序
不能使用@Listeners批注將此偵聽器添加到執行中。
5.-小結
好了,今天關於TestNG之依賴注入,就分享到這里。