0

我试图并行运行我的 JUnit 类,每次运行测试时都会遇到不同的错误。有时 ClassA 失败,有时 ClassB 失败,有时没有失败。

我正在使用 maven-surefire-plugin(版本 2.19.1)和 JUnit 4.8。我注意到我得到的异常是来自 EasyMock 的断言错误。问题似乎是当我有一个创建 Logger 类 (log4j) 实例的类时,内部调用“RepositorySelector.getLoggerRepository()”来获取给定“类名”的 Logger。当它并行运行时,多个类会创建一个 Logger 实例,并且 EasyMock 检测到“RepositorySelector.getLoggerRepository()”的调用次数超过了预期的调用次数。

这里有一个例子:

public class ClassA{
    private static final Logger LOGGER = Logger.getLogger(ClassA.class);
    public void someMethod(){
        LOGGER.info("SomeMethod");
    }
}

public class ClassB{
    private static final Logger LOGGER = Logger.getLogger(ClassB.class);
    public void someMethodB(){
        LOGGER.info("SomeMethodB");
    }
}    

public class ClassATest{
    private ClassA classUnderTest;
    @Before
    public void setUp(){
        classUnderTest = new ClassA();
    }

    @Test
    public void testSomeMethod(){
        classUnderTest.someMethod();
    }
}

public class ClassBTest{
    private ClassB classUnderTest;
    @Before
    public void setUp(){
        classUnderTest = new ClassB();
    }

    @Test
    public void testSomeMethodB(){
        classUnderTest.someMethodB();
    }
}

我的 pom.xml 上有这个配置

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.19.1</version>
    <configuration>
        <forkMode>once</forkMode>
        <!-- Parallel classes -->
        <parallel>classes</parallel>
        <threadCountClasses>2</threadCountClasses>
    </configuration>
</plugin>

对我来说,好像两个测试同时运行,每个测试都执行@Before方法(setUp方法)并调用ClassA或B的构造函数,它创建了一个Logger类的新实例,并且出于某种原因EasyMock是尝试验证次数,并且在哪里出现断言错误。那是我缺少的东西吗?还是 EasyMock 无法处理的事情?

我最初的项目有一百个 JUnit 测试,几乎所有的测试都在记录一些信息。如果我禁用“并行”选项,一切正常。有时我得到断言错误,其他时候我得到一个 NullPointerException 像 @Before 方法永远不会被执行,它试图执行 @Test 方法并抛出 NPE 因为它之前没有初始化。(这种情况发生了几次)。

有什么想法吗?我在这里错过了什么吗?

Java版本:jdk1.7.0_55 Maven:apache-maven-3.2.5 Junit:4.8.2 Maven Surefire插件:2.19.1 EasyMock:3.2(easymockclassextension)

4

1 回答 1

0

如果您并行运行,您的测试必须与 Java 内存模型一致。这似乎是你的主要问题。

首先,从您所说RepositorySelector的来看,您的所有测试似乎都共享了一个模拟。所以我猜它可能会被并行调用两次。您可以设置 EasyMock 期望以匹配它(andStubReturn而不是andReturn)。

那么,NPE 可能与 EasyMock 无关。同样,我没有足够的信息来确定我的答案,但它看起来像是出版问题。一个线程设置了一个非易失性的属性,因此另一个线程看不到它。我不知道实例创建和实例@Before是否发生在同一个线程中。这可以解释问题。您可以通过System.out.println(Thread.currentThread())在构造函数和@Before. 或者您可以设置所有内容volatile,它可能会解决您的问题。

我还建议将 EasyMock 更新到 3.4,将 JUnit 更新到 4.12,因为两者可能都有一些并发修复。

最后,EasyMock 支持多线程。因此,除非有错误,否则那一侧应该没有任何问题。

于 2017-03-29T14:32:10.100 回答