强制 TestNG 为每个方法测试创建新实例
force TestNG to create new instance for every method test
根据这些链接:
TestNG 不会在每个方法测试中创建新实例。
我有 spring 启动应用程序。我需要编写集成测试(控制器、服务、存储库)。有时为了创建新的测试用例,我需要数据库中的一些实体。为了忘记 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)
}
我需要为每个下一个增加 times(N) method.I 明白这是 testng 实现,但我试图为我找到好的解决方案。对于我的服务,我使用构造函数自动装配并且所有字段都是最终字段。
问题:
是否可以强制testng为每个方法测试创建新实例?
我可以为每个方法测试重新创建 spring 上下文吗?
我可以为每个模拟存储库创建自定义代理并通过我的代理在 @BeforeMethod 方法中重置模拟吗?
实际上我不需要在上下文中创建新的存储库模拟实例,我只需要重置它们的状态。
到目前为止,我认为 Mockito.reset(mock) 只是创建新实例并将其分配给引用 mock。 但事实并非如此。 Mockito.reset 的真实行为只是在不创建新模拟实例的情况下清理模拟的当前状态。
我的解决方案:
import org.springframework.data.repository.Repository;
@Autowired
private List<Repository> mockedRepositories;
@BeforeMethod
public void before() {
mockedRepositories.forEach(Mockito::reset);
}
此代码自动装配在 ApplicationContextInitializer 中模拟的所有存储库,并重置它们的状态。
现在我可以不用 times(2)
使用 verify()
@Test
public void test2() throws Exception {
mySevice.execute()
verify(studentRepository).findOne(notNull(String.class));
}
根据这些链接: TestNG 不会在每个方法测试中创建新实例。
我有 spring 启动应用程序。我需要编写集成测试(控制器、服务、存储库)。有时为了创建新的测试用例,我需要数据库中的一些实体。为了忘记 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)
}
我需要为每个下一个增加 times(N) method.I 明白这是 testng 实现,但我试图为我找到好的解决方案。对于我的服务,我使用构造函数自动装配并且所有字段都是最终字段。
问题:
是否可以强制testng为每个方法测试创建新实例? 我可以为每个方法测试重新创建 spring 上下文吗?
我可以为每个模拟存储库创建自定义代理并通过我的代理在 @BeforeMethod 方法中重置模拟吗?
实际上我不需要在上下文中创建新的存储库模拟实例,我只需要重置它们的状态。 到目前为止,我认为 Mockito.reset(mock) 只是创建新实例并将其分配给引用 mock。 但事实并非如此。 Mockito.reset 的真实行为只是在不创建新模拟实例的情况下清理模拟的当前状态。
我的解决方案:
import org.springframework.data.repository.Repository;
@Autowired
private List<Repository> mockedRepositories;
@BeforeMethod
public void before() {
mockedRepositories.forEach(Mockito::reset);
}
此代码自动装配在 ApplicationContextInitializer 中模拟的所有存储库,并重置它们的状态。 现在我可以不用 times(2)
使用 verify()@Test
public void test2() throws Exception {
mySevice.execute()
verify(studentRepository).findOne(notNull(String.class));
}