当前位置: 首页 > 知识库问答 >
问题:

共享模拟并行测试

柴亦
2023-03-14

我正在编写一个单元测试类(使用testng),它模拟了成员变量(使用Mockito),并并行运行测试。我最初在@BeForeClass方法中设置了预期的mock,在每个测试用例中,我通过为每个异常情况创建mockito.when来破坏一些东西。

我所看到的(不出所料)是这些测试不是独立的;当一个测试用例中的mockito.when会影响其他测试用例。我注意到可以在每次测试之前设置模拟,因此我将@BeForeClass更改为@BeForeMethod。我仍然没想到这些测试会一致通过,因为所有测试仍然同时在同一个共享模拟对象上运行。然而,所有的测试开始一致通过。我的问题是“为什么”?这最终会失败吗?无论我做什么(线程、睡眠等),我都不能重现失败。

使用@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");
    }
}

共有1个答案

汤飞翮
2023-03-14

这里的问题是TestNG创建了测试类exampletest的一个实例,并且这是由@test两个方法使用的实例。

因此,当您使用@beforeClass时,如果TestExceptionalCase()首先运行并更改了测试类的状态,则TestNormalCase()将随机失败。

当您将注释更改为@BeforeMethod时,将导致安装程序在每个@test方法执行之前执行。

但是在一种情况下,您的设置仍然会失败,即当您在TestNG套件xml文件中的 标记中使用parallel=“methods”属性时,即当您配置TestNG并指示它并行运行每个@test方法时。

在这种情况下,TestExceptionalCase()中的mockito.when()将影响共享状态[因为您在所有@test方法中以共享的方式使用this],导致TestNormalCase()随机失败。

为了解决这个问题,我建议您执行以下操作:

  • 不要在@test方法之间共享,而是将其单独放置在测试类之外,即将测试类的所有数据成员放置在单独的pojo中,而不是对进行模拟。
  • 使用ThreadLocal存储mockito.when()模拟的状态,然后从@test方法中对ThreadLocal运行断言。
 类似资料:
  • 我使用CSV馈送器来馈送多个模拟。当使用gatlingRun运行时,每个模拟从一开始就开始读取文件。我将进料器保存在对象变量中(必须像静态变量一样): 有没有办法让所有模拟都使用相同的馈线实例,或者让每个实例在其他实例完成的地方继续?

  • 目标:独立并行地运行两个类,每个测试将方法名存储到一个变量中,该变量可以在测试中稍后访问。 问题:当测试并行运行时,它们开始在它们之间共享数据,从而损坏测试。 如果您看到控制台输出,这是错误的: 因为这是两个独立的类和方法正在运行。我在这里设置了正确的名字: 输出应该是这样的: 种皮 } 测试B } 帮助者方法 Testng.xml 控制台输出

  • 共享模块 Nest Modules can export their components. It means that we can easily share component instance between them. The best way to share an instance between two or more modules is to create Shared Modu

  • 共享内存 在消息传递之外,还存在一种广为人知的并发模型,那就是共享内存。其实如果不能共享内存,消息传递也是不能在不同的线程间传递消息,也谈不上在不同的线程间等待和通知了。共享内存是这一切得以发生的基础。如果查看源码,你会发现消息传递的内部实现就是借用了共享内存机制。相对于消息传递而言,共享内存会有更多的竞争,但是不用进行多次拷贝,在某些情况下,也需要考虑使用这种方式来处理。在Rust中,能共享内存

  • 嗨,我想在appium上使用ios模拟器并行运行ios测试用例。我知道MAC会有限制,因为只有一个模拟器会启动,但有没有后门入口可以让它们并行运行,我不想使用网格,因为有一些原因,所以有没有办法在ios模拟器上并行运行ios测试用例。 如果我一次运行两个不同端口和地址的appium服务器,只有一个ios模拟器会启动,因为它会关闭另一个。 我使用的是1.6.4 appium服务器和Xcode 8。

  • 当单元测试共享首选项时,值是否为get refresh every test?