无法使用maven surefire插件和EasyMock运行并行测试

时间:2017-03-28 15:44:41

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

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

我正在使用maven-surefire-plugin(版本2.19.1)和JUnit 4.8。我注意到的是我得到的异常是EasyMock的断言错误。问题似乎是当我有一个创建Logger类(log4j)实例的类时,内部调用“RepositorySelector.getLoggerRepository()”来获取Logger给出的“classname”。当它并行运行时,多个类创建一个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 for某种原因是试图验证次数,并且我在哪里得到断言错误。这是我缺少的东西吗?或者是EasyMock无法处理的东西?

我的原始项目有几百个JUnit测试,几乎所有测试都记录了一些信息。如果我禁用了“并行”选项,一切正常。 有时候我得到了断言错误,其他的我得到了一个N​​ullPointerException,就像@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)

1 个答案:

答案 0 :(得分:0)

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

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

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

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

最后,EasyMock支持多线程。所以除非有错误,否则不应该有任何问题。