我在这里有一个有趣的 JUnit 问题(JUnit 4.12)。我有一个只有静态方法的基类。由于它们的使用方式,它们必须是静态的。我从基类继承其他类。所以,如果基类是Base
,我们有ChildA
和ChildB
。
大多数方法都包含在基类中,但它必须知道它实际上是哪个子类(只是调用这些方法作为基类是无效的)。这是通过基类中的静态数据成员完成的:
public class Base {
protected static ChildType myType = ChildType.Invalid;
...
}
每个孩子通过静态初始化器设置数据成员,因此:
static {
myType = ChildType.ChildA;
}
然后当方法被调用时,基类知道它是什么类型并加载适当的配置(类型实际上是一个配置名称)。
这一切都在运行应用程序时完美运行。在调试器中单步执行它并通过日志消息,我可以看到设置了适当的类型,并且方法根据子类型加载了适当的配置。
使用 JUnit 时会出现问题。我们有一些 JUnit 测试来测试每个基类方法。由于只调用基类的方法是无效的,我们调用子类的方法,因此:
bool result = ChildA.methodTwo();
这“总是失败”。为什么?静态初始化程序永远不会被调用。当将代码作为应用程序运行时,它会被调用,每个人都很高兴。当我将它作为 JUnit 测试运行时,会跳过静态初始化程序并且方法具有无效数据。JUnit 在做什么来跳过静态初始化程序?有办法解决吗?
细节
实际上,我们并没有像我上面发布的那样调用该方法。我只是希望这个例子尽可能清楚。实际上,我们有一个用 Jersey 框架编写的 Web 服务。调用的方法是 REST 端点之一。
@POST
@Produces(MediaType.TEXT_PLAIN)
public String methodPost() {
...
return new String( itWorked ? "success" : "fail" );
}
我们这样称呼它(对于丑陋的语法感到抱歉,这就是它的工作方式):
@Test
public void testThePost() throws Exception {
javax.ws.rs.core.Response response = target("restapi/").request().post(Entity.entity(null, MediaType.TEXT_PLAIN));
assertEquals( 200, response.getStatus() );
}
所有的 GET 测试都有效,并且所有这些测试都调用了静态初始化程序。只是这个 POST 失败了,而且只有在运行 JUnit 测试时才会失败。