Java自动化测试框架-09 - TestNG之依赖注入篇 (详细教程)

1.-依赖注入

TestNG支持两种不一样类型的依赖项注入:本机(由TestNG自己执行)和外部(由诸如Guice的依赖项注入框架执行)。java

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注释本地注入的参数类型:ide

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);
  }
 
}

若是须要更大的灵活性来指定应使用哪些模块实例化测试类,则能够指定模块工厂:ui

/**
 * @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:this

/**
 * @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文件中定义父模块的方法:spa

<suite parent-module="com.example.SuiteParenModule" guice-stage="PRODUCTION">
</suite>

对于给定的套件,TestNG将只建立一次此模块。还将使用该模块获取特定于测试的Guice模块和模块工厂的实例,而后将为每一个测试类建立子注入器。经过这种方法,您能够在父模块中声明全部公共绑定,也能够在模块和模块工厂中注入在父模块中声明的绑定。这是此功能的示例:code

/**
 * @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之依赖注入,就分享到这里。

相关文章
相关标签/搜索