运行JUnit测试时不执行静态类初始化

时间:2013-02-01 09:07:23

标签: java static junit initialization cobertura

我有一个带有一些静态字段的java类:

private static final PDMapCacheDAO REST_CACHE_DAO = 
    new PDMapCacheDAOImpl( Constants.REST_CACHE_NAME );

private static final PDMapCacheDAO HOLIDAYS_CACHE_DAO = 
    new PDMapCacheDAOImpl( Constants.HOLIDAYS_CACHE_NAME );

private static final String[] DATE_ARRAY = { "D", "0", "1", "2", "3", "C" };

并且JUnit测试模拟了REST_CACHE_DAO和HOLIDAYS_CACHE_DAO的初始化行为:

final PDMapCacheDAOImpl holidaysMapCacheDAOImpl = mock(PDMapCacheDAOImpl.class);
final PDMapCacheDAOImpl restMapCacheDAOImpl = mock(PDMapCacheDAOImpl.class);

whenNew(PDMapCacheDAOImpl.class).withArguments(Constants.HOLIDAYS_CACHE_NAME).thenReturn(holidaysMapCacheDAOImpl);
whenNew(PDMapCacheDAOImpl.class).withArguments(Constants.REST_CACHE_NAME).thenReturn(restMapCacheDAOImpl);

当单独执行测试时,测试按预期执行,但是当所有JUnit测试一起执行时(从带有Run As的Java项目 - > Junit测试),测试会给出空指针异常。

我做了一些调试,我发现问题(如标题中所述)是静态类未初始化 - 当调用静态方法时,REST_CACHE_DAO和HOLIDAYS_CACHE_DAO为空。不调用PDMapCacheDAOImpl的构造函数并且不注入模拟,因此当我们使用它们时,它会给出一个NPE。

我已经阅读了一些执行测试的工具,比如eclemma有这个错误(某些静态类没有初始化)。在这种情况下,解决方案是包含-f选项。

这是Eclemma网站关于这个问题的说法:“

  

2.8。 EMMA如何定义班级覆盖范围?   首先,一个类需要被认为是可执行的,甚至可以考虑覆盖。如果已由JVM加载并初始化,则认为可执行类已被覆盖。类初始化意味着执行类静态构造函数(如果有)。请注意,即使没有执行其他方法,也可以覆盖类。在没有-f选项的情况下使用emmarun时,通常会看到少量已加载但未初始化的类。   EMMA会报告课程覆盖范围,以便您可以发现您的测试套件似乎没有“触及”的课程:它们可能是死代码,也可能需要更多测试注意。

有趣的是,我们没有使用Eclemma,我们正在使用Cobertura,但行为和错误是相同的。

有没有人知道Cobertura中的这个错误以及如何解决它? (在Cobertura或通用方式)?

2 个答案:

答案 0 :(得分:0)

这是推测性的。

我猜PDMapCacheDAO是一个接口/抽象类,它使用PDMapCacheDAOImpl来表示某些常量。

PDMapCacheDAOImpl实现/扩展PDMapCacheDAO。正确?

当我发现这是一个技术上难看的解决方案(reciproke依赖项)时,请使用这些常量创建一个单独的接口PDMapCacheDAOs

这可能会解决问题。

答案 1 :(得分:0)

最后我们决定使用Singleton,避免静态初始化的所有问题。我不得不对公司说,问题仍然存在并且将来可能会再次发生,但我不能等待SQA团队解决它。

感谢您的所有回复和时间