我尝试并行运行我的 JUnit 类,每次运行测试时都会收到不同的错误。有时A类失败,有时B类失败,有时什么都没有失败。
我正在使用maven-surefire-plugin(版本2.19.1)和JUnit 4.8。我注意到的是我得到的异常是来自 EasyMock 的断言错误。问题似乎是当我有一个类创建记录器类(log4j)的实例时,内部调用"RepositorySelector.getLoggerRepository()"来获取记录器一个"类名"。当它并行运行时,多个类会创建 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();
}
}
我的绒球上有这个配置.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,因为它以前没有初始化。(这种情况很少发生)。
有什么想法吗?我在这里错过了什么吗?
爪哇版本:jdk1.7.0_55 Maven: apache-maven-3.2.5 朱尼特:4.8.2 Maven Surefire插件:2.19.1 EasyMock: 3.2 (easymockclassextension)
如果并行运行,则测试必须与 Java 内存模型一致。这似乎是你的主要问题。
首先,从你所说的RepositorySelector
是一个模拟,似乎与你的所有测试共享。所以我想它可能会被并行调用两次。您可以设置 EasyMock 期望以匹配该期望(andStubReturn
而不是andReturn
)。
那么,NPE可能与EasyMock无关。同样,我没有足够的信息来明确我的答案,但它看起来像是出版问题。一个线程设置一个不易失的属性,因此另一个线程看不到它。我不知道实例创建和@Before
是否发生在同一个线程中。这可以解释问题。您可以通过在构造函数和@Before
中执行System.out.println(Thread.currentThread())
来确认这一点。或者你可以volatile
设置所有内容,它可能会解决你的问题。
我还建议将 EasyMock 更新到 3.4,将 JUnit 更新到 4.12,因为两者都可能有一些并发修复。
最后,EasyMock支持多线程。因此,除非存在错误,否则该方面应该没有任何问题。