Chr*_*isV 2 concurrency testng unit-testing mocking mockito
我正在编写一个单元测试类(使用testng),它已经模拟了成员变量(使用Mockito)并且并行运行测试.我最初在@BeforeClass方法中设置了预期的模拟,并且在每个测试用例中,我通过为每个例外情况创建一个Mockito.when来破坏某些东西.
我所看到的(不足为奇)是这些测试不是独立的; Mockito.when在一个测试用例中会影响其他测试用例.我注意到我可以在每次测试之前设置模拟,然后将@BeforeClass更改为@BeforeMethod.我仍然没有想到这些会持续传递,因为测试仍然同时在同一个共享模拟对象上运行.但是,所有测试都开始一致地通过.我的问题是"为什么"?这最终会失败吗?无论我做什么(Thread.sleep等)我都无法重现失败.
使用@BeforeMethod足以使这些测试独立吗?如果是这样,有人可以解释为什么吗
示例代码如下:
public class ExampleTest {
@Mock
private List<String> list;
@BeforeClass // Changing to @BeforeMethod works for some reason
public void setup() throws NoSuchComponentException, ADPRuntimeException {
MockitoAnnotations.initMocks(this);
Mockito.when(list.get(0)).thenReturn("normal");
}
@Test
public void testNormalCase() throws InterruptedException {
assertEquals(list.get(0), "normal"); // Fails with expected [normal] but found [exceptional]
}
@Test
public void testExceptionalCase() throws InterruptedException {
Mockito.when(list.get(0)).thenReturn("exceptional");
assertEquals(list.get(0), "exceptional");
}
}
Run Code Online (Sandbox Code Playgroud)
这里的问题是TestNG创建了一个测试类ExampleTest的实例,这是两个@Test方法使用的实例.
因此,当您使用时@BeforeClass,testNormalCase()如果testExceptionalCase()先运行并改变测试类的状态,则会出现随机故障.
当您将注释更改为时@BeforeMethod,将导致在执行每个@Test方法之前执行设置.
因此,设置将修复状态,testNormalCase()这就是它将通过的原因,并且由于testExceptionalCase()内部使用Mockito.when()然后运行断言来改变状态,所以它也会一直传递.
但是有一种情况,您的设置仍然会失败,即,当您在TestNG套件xml文件中使用标记中的parallel="methods"属性时,<suite>即,当您配置TestNG并指示它@Test并行运行每个方法时.
在这种情况下,Mockito.when()内部testExceptionalCase()将影响共享状态[因为您this在所有@Test方法中以共享方式使用]导致testNormalCase()随机失败.
要解决这个问题,我建议您执行以下操作:
this在你的@Test方法之间共享,而是在测试类之外单独存放,即将测试类的所有数据成员放在一个单独的pojo中,这将被嘲笑而不是嘲笑this.ThreadLocal来存储被模拟的状态,Mockito.when()然后ThreadLocal在@Test方法中的from 上运行断言.