【问题标题】:Unable to run parallel tests using maven surefire plugin and EasyMock无法使用 maven surefire 插件和 EasyMock 运行并行测试
【发布时间】:2017-03-28 15:44:41
【问题描述】:

我尝试并行运行我的 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 六月:4.8.2 Maven Surefire 插件:2.19.1 EasyMock:3.2(easymockclassextension)

【问题讨论】:

    标签: logging junit4 easymock maven-surefire-plugin parallel-testing


    【解决方案1】:

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

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

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

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

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

    【讨论】:

    • 谢谢 Henri,我会测试这两种方法,我会先升级库,然后分享我的结果!
    • 所以.. 我将 easymock 从 3.2 升级到 3.4,将 Junit 4.8.2 升级到 4.12,我得到了同样的错误。
    • 所以..我将easymock从3.2升级到3.4,将Junit 4.8.2升级到4.12,我得到了同样的错误。现在我正在尝试记录当前线程,我注意到的是......我的类 ClassA 或 ClassB 甚至没有创建,因为 java 在解析对象之前首先实例化了静态字段(Logger)。由于该错误,easymock 失败了。这就是我获得NPE的原因。并且@before 和构造函数在同一个线程上运行。
    • 是的。静态属性首先完成。所以RepositorySelector 的模拟也应该是静态的。
    猜你喜欢
    • 2021-05-16
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-05
    • 2014-11-08
    • 1970-01-01
    相关资源
    最近更新 更多