2016-05-16 91 views
0

根据以下链接:https://stackoverflow.com/a/20056622/1623597https://stackoverflow.com/a/15640575/1623597 TestNG不会在每个方法测试中创建新实例。强制TestNG为每个方法测试创建新实例

我有spring引导应用程序。我需要编写集成测试(Controller,service,Repositories)。有时候要创建新的测试用例,我需要在DB中使用一些实体。要忘记db中的任何预定义实体,我决定模拟库层。我刚刚实现了ApplicationContextInitializer,它可以在类路径中找到所有JPA Repository,并将它们添加到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) 
} 

我需要增加每一个后续method.I次(N)了解到,这是TestNG的实现,但我试图找到很好的解决方案给我。对于我的服务,我使用构造函数自动装配,所有字段都是最终的。

问题:

  1. 是否有可能迫使TestNG的为每个测试方法创建新实例? 我可以为每个方法测试重新创建弹簧上下文吗?

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

+0

你已经尝试重置你想要在@/AfterMethod之前? – juherr

+0

我不能使用这种方法。原因是我可以有10个存储库,在另外20个服务中使用。每一项服务都使用构造函数自动装配并且具有最终字段。此外,我无法在@ Before/AfterMethod中覆盖所有服务并替换mocks – Geniy

+0

如何初始化myService? – juherr

回答

0

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

我的解决办法:

import org.springframework.data.repository.Repository; 

@Autowired 
private List<Repository> mockedRepositories; 

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

此代码自动装配在ApplicationContextInitializer被嘲笑,所有的回购协议,并重置它们的状态。 现在,我可以使用验证()没有时间(2)

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