我试图并行运行我的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测试,几乎所有测试都记录了一些信息。如果我禁用了“并行”选项,一切正常。 有时候我得到了断言错误,其他的我得到了一个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)
答案 0 :(得分:0)
如果并行运行,则测试必须与Java内存模型一致。这似乎是你的主要问题。
首先,根据您所说的RepositorySelector
是一个看似所有测试共享的模拟。所以它可能被并行调用两次我猜。您可以设置EasyMock期望值(andStubReturn
而不是andReturn
)。
然后,NPE可能与EasyMock无关。同样,我没有足够的信息来确定我的答案,但它看起来像出版物问题。一个线程设置了一个非易失性的属性,因此另一个线程看不到它。我不知道实例创建和@Before
是否在同一个线程中发生。这可以解释这个问题。您可以在构造函数和System.out.println(Thread.currentThread())
中执行@Before
来确认。或者您可以设置所有内容volatile
,它可以解决您的问题。
我还建议将EasyMock更新为3.4,将JUnit更新为4.12,因为两者中可能都有一些并发修复。
最后,EasyMock支持多线程。所以除非有错误,否则不应该有任何问题。