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

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批注将此侦听器添加到执行中。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏北京宏哥

Java自动化测试框架-04 - TestNG之Test Method篇 - 道法自然,法力无边(详细教程)

测试方法是可以带有参数的。每个测试方法都可以带有任意数量的参数,并且可以通过使用TestNG的@Parameters向方法传递正确的参数。

13120
来自专栏用户5521492的专栏

使用 idea 搭建 SSM 项目

Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-On...

5230
来自专栏java思维导图

为啥mybatis的mapper只有接口没有实现类,但它却能工作?

说起mybatis,大伙应该都用过,有些人甚至底层源码都看过了。在mybatis中,mapper接口是没有实现类的,取而代之的是一个xml文件。也就是说我们调用...

29420
来自专栏绿盟科技安全情报

【漏洞预警】Jackson-databind远程代码执行(CVE-2019-12384)预警通告

6月21日,Redhat官方发布jackson-databind漏洞(CVE-2019-12384)安全通告,多个Redhat产品受此漏洞影响,CVSS评分为8...

8310
来自专栏Android补给站

Android Navigation的四大要点你都知道吗?

在JetPack中有一个组件是Navigation,顾名思义它是一个页面导航组件,相对于其他的第三方导航,不同的是它是专门为Fragment的页面管理所设计的...

26930
来自专栏绿盟科技安全情报

Weblogic CVE-2019-2725 分析报告

这个漏洞最先由某厂商报给某银行,某银行再将该信息报给CNVD,后CNVD通告:“国家信息安全漏洞共享平台(CNVD)收录了由中国民生银行股份有限公司报送的Ora...

4600
来自专栏咸鱼学Python

字体加密 | 猫眼榜单字体解密(性感咸鱼,在线炒冷饭)

猫眼的字体加密相信大家都很熟悉,每一个分析字体加密的博主都会写一次字体加密,没写过至少也会做过。

12810
来自专栏D·技术专栏

Spring注解式编程

相比较XML配置来说,当项目过大的时候难以维护。Spring还有一种支持0配置的注解式编程。

7230
来自专栏成猿之路

SpringBoot+Mybatis+Swagger2环境搭建

SpringBoot相对于传统的SSM框架的优点是提供了默认的样板化配置,简化了Spring应用的初始搭建过程,如果你不想被众多的xml配置文件困扰,可以考虑使...

12410
来自专栏中科院渣渣博肆僧一枚

python lxml中etree的简单应用

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

12850

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励