【问题标题】:force TestNG to create new instance for every method test强制 TestNG 为每个方法测试创建新实例
【发布时间】:2016-09-12 08:33:17
【问题描述】:

根据这些链接:https://stackoverflow.com/a/20056622/1623597 https://stackoverflow.com/a/15640575/1623597 TestNG 不会在每个方法测试上创建新实例。

我有弹簧启动应用程序。我需要编写集成测试(控制器、服务、存储库)。有时要创建新的测试用例,我需要数据库中的一些实体。为了忘记 db 中的任何预定义实体,我决定模拟存储库层。我刚刚实现了 ApplicationContextInitializer,它可以在类路径中找到所有 JPA 存储库并将它们的模拟添加到 spring 上下文中。

我遇到了一个新问题,即每个 ControllerTest(扩展 AbstractTestNGSpringContextTests)创建一次我的模拟。测试的上下文只创建一次,所有方法的模拟实例都是相同的。现在,我有

//All repos are mocked via implementation of ApplicationContextInitializer<GenericWebApplicationContext>
// and added to spring context by
//applicationContext.getBeanFactory().registerSingleton(beanName, mock(beanClass));   //beanClass in our case is StudentRepository.class
@Autowired
StudentRepository studentRepository;

//real MyService implementation with autowired studentRepository mock
@Autowired
MyService mySevice;

@Test
public void test1() throws Exception {
    mySevice.execute();     //it internally calls studentRepository.findOne(..); only one time
    verify(studentRepository).findOne(notNull(String.class));
}

//I want that studentRepository that autowired to mySevice was recreated(reset)
@Test
public void test2() throws Exception {
    mySevice.execute();     //it internally calls studentRepository.findOne(..); only one time
    verify(studentRepository, times(2)).findOne(notNull(String.class)); //I don't want to use times(2)
    //times(2) because studentRepository has already been invoked in test1() method

}

@Test
public void test3() throws Exception {
    mySevice.execute();     //it internally calls studentRepository.findOne(..); only one time
    verify(studentRepository, times(3)).findOne(notNull(String.class)); //I don't want to use times(3)
}

我需要为每个下一个方法增加次数(N)。我知道它是 testng 实现,但我试图为我找到好的解决方案。对于我的服务,我使用构造函数自动装配,并且所有字段都是最终的。

问题:

  1. 是否可以强制 testng 为每个方法测试创建新实例? 我可以为每个方法测试重新创建 spring 上下文吗?

  2. 我可以为每个模拟存储库创建自定义代理并通过我的代理在 @BeforeMethod 方法中重置模拟吗?

【问题讨论】:

  • 您是否已经尝试在 @Before/AfterMethod 中重置您想要的内容?
  • 我不能使用这种方法。原因是我可以有 10 个存储库,用于另外 20 个服务。每个服务都使用构造函数自动装配并具有最终字段。此外,我无法通过所有服务并替换 @Before/AfterMethod 中的模拟
  • 如何初始化myService?
  • 这是 Spring Boot 应用程序。我刚刚添加了@_Service 注释。该服务在构造函数之前有@_Autowired(用于自动装配回购等)
  • 能分享一下完整的测试课吗?

标签: spring-mvc mockito testng


【解决方案1】:

实际上我不需要在上下文中创建新的存储库模拟实例,我只需要重置它们的状态。 到目前为止,我认为 Mockito.reset(mock) 只是创建新实例并将其分配给引用模拟。 但事实并非如此。 Mockito.reset 的真实行为只是为 mock 清除当前状态,而不创建新的 mock 实例。

我的解决方案:

import org.springframework.data.repository.Repository;

@Autowired
private List<Repository> mockedRepositories;

@BeforeMethod
public void before() {
    mockedRepositories.forEach(Mockito::reset);
}

此代码自动装配在 ApplicationContextInitializer 中模拟的所有 repos,并重置它们的状态。 现在我可以不用times(2)来使用verify()了

@Test
public void test2() throws Exception {
    mySevice.execute()
    verify(studentRepository).findOne(notNull(String.class));
}

【讨论】:

    猜你喜欢
    • 2013-03-15
    • 2019-09-23
    • 2021-09-13
    • 1970-01-01
    • 1970-01-01
    • 2011-09-27
    • 1970-01-01
    • 2011-04-16
    • 1970-01-01
    相关资源
    最近更新 更多