Log4j Logger.getLogger(Class) 在与 jMockit 和 Cobertura 一起运行时抛出 NPE

2024-01-31

我发现 cobertura-maven-plugin 2.6 和 jmockit 1.8 之间存在奇怪的交互。我们的生产代码中的一个特定模式有一个带有许多静态方法的类,这些静态方法有效地包装了一个像单例一样的不同类。为这些类编写单元测试进展顺利,直到我尝试使用 cobertura 运行覆盖率报告时,出现了以下错误:

java.lang.ExceptionInInitializerError
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252)
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141)
    at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
    at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
    at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)
Caused by: java.lang.NullPointerException
    at com.example.foo.MySingleton.<clinit>(MySingleton.java:7)
    ... 13 more

这会导致NoClassDefFoundError并且无法初始化单例类。这是一个完整的 SSCCE(我能得到的最短的),它复制了错误;第 7 行MySingleton is Logger.getLogger().

这里是“单例”...

package com.example.foo;

import org.apache.log4j.Logger;

public class MySingleton {

    private static final Logger LOG = Logger.getLogger(MySingleton.class);

    private boolean inited = false;
    private Double d;

    MySingleton() {
    }

    public boolean isInited() {
        return inited;
    }

    public void start() {
        inited = true;
    }

    public double getD() {
        return d;
        }
}

还有静态类...

package com.example.foo;

import org.apache.log4j.Logger;

public class MyStatic {

    private static final Logger LOGGER = Logger.getLogger(MyStatic.class);

    private static MySingleton u = new MySingleton();

    public static double getD() {
        if (u.isInited()) {
            return u.getD();
        }
        return 0.0;
    }

}

以及打破一切的测试......

package com.example.foo;

import mockit.Expectations;
import mockit.Mocked;
import mockit.Tested;

import org.junit.Test;

public class MyStaticTest {

    @Tested MyStatic myStatic;

    @Mocked MySingleton single;

    @Test
    public void testThatBombs() {
        new Expectations() {{
            single.isInited(); result = true;
            single.getD(); /*result = 1.2;*/
        }};

//        Deencapsulation.invoke(MyStatic.class, "getD");
        MyStatic.getD();

    }

}

和 Maven pom:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example.foo</groupId>
    <artifactId>test</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Test</name>

    <dependencies>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.16</version>
        </dependency>

        <dependency>
            <groupId>org.jmockit</groupId>
            <artifactId>jmockit</artifactId>
            <version>1.8</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>cobertura-maven-plugin</artifactId>
                    <version>2.6</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>

</project>

总结一下:运行普通单元测试时(mvn clean test),上面测试就好了;当与 cobertura 一起运行时(mvn clean cobertura:cobertura)它会抛出顶部显示的一组令人讨厌的异常。显然是某个地方的错误,但是是谁的?


这个问题的原因并不是 bug,而是 JMockit 在模拟包含静态初始值设定项的类时缺乏鲁棒性。 JMockit的下一个版本(1.9)将在这一点上进行改进(我已经有了一个可行的解决方案)。

此外,如果 Cobertura 将其生成的方法(其中四个名称以“__cobertura_”开头,添加到每个检测类中)标记为“合成”,则不会出现该问题,以便 JMockit 在模拟 Cobertura 检测时会忽略它们班级。无论如何,幸运的是这没有必要。

目前,有两种简单的解决方法可以避免该问题:

  1. 确保在测试开始时 JVM 已初始化任何要模拟的类。这可以通过实例化它或调用它的静态方法来完成。
  2. 将模拟字段或模拟参数声明为@Mocked(stubOutClassInitialization = true).

这两种解决方法都可以防止 NPE 从静态类初始值设定项内部抛出,该初始值设定项由 Cobertura 修改(要查看这些字节码修改,您可以使用javapJDK 的工具,在类下target/generated-classes目录)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Log4j Logger.getLogger(Class) 在与 jMockit 和 Cobertura 一起运行时抛出 NPE 的相关文章

  • 为什么 JTables 使 TableModel 在呈现时不可序列化?

    所以最近我正在开发一个工具 供我们配置某些应用程序 它不需要是什么真正令人敬畏的东西 只是一个具有一些 SQL 脚本生成功能并创建几个 XML 文件的基本工具 在此期间 我使用自己的 AbstractTableModel 实现创建了一系列
  • .properties 中的通配符

    是否存在任何方法 我可以将通配符添加到属性文件中 并且具有所有含义 例如a b c d lalalala 或为所有以结尾的内容设置一个正则表达式a b c anything 普通的 Java 属性文件无法处理这个问题 不 请记住 它实际上是
  • 为 java 游戏创建交互式 GUI

    大家好 我正在创建一个类似于 java 中的 farmville 的游戏 我只是想知道如何实现用户通常单击以与游戏客户端交互的交互式对象 按钮 我不想使用 swing 库 通用 Windows 看起来像对象 我想为我的按钮导入自定义图像 并
  • 如何使用assertEquals 和 Epsilon 在 JUnit 中断言两个双精度数?

    不推荐使用双打的assertEquals 我发现应该使用带有Epsilon的形式 这是因为双打不可能100 严格 但无论如何我需要比较两个双打 预期结果和实际结果 但我不知道该怎么做 目前我的测试如下 Test public void te
  • 构建/部署 EJB .jar 及其依赖项

    我是 Java EE 新手 我使用 Maven Eclipse 和 jBoss WildFly 我有一个war项目 当我构建项目时 它的所有依赖项都打包在war文件输入WEB INF lib 现在我正在尝试创建一个ejb项目 我有
  • 过滤两次 Lambda Java

    我有一个清单如下 1 2 3 4 5 6 7 和 预期结果必须是 1 2 3 4 5 6 7 我知道怎么做才能到7点 我的结果 1 2 3 4 5 6 我也想知道如何输入 7 我添加了i gt i objList size 1到我的过滤器
  • HSQL - 识别打开连接的数量

    我正在使用嵌入式 HSQL 数据库服务器 有什么方法可以识别活动打开连接的数量吗 Yes SELECT COUNT FROM INFORMATION SCHEMA SYSTEM SESSIONS
  • 没有 Spring 的自定义 Prometheus 指标

    我需要为 Web 应用程序提供自定义指标 问题是我不能使用 Spring 但我必须使用 jax rs 端点 要求非常简单 想象一下 您有一个包含键值对的映射 其中键是指标名称 值是一个简单的整数 它是一个计数器 代码会是这样的 public
  • volatile、final 和synchronized 安全发布的区别

    给定一个带有变量 x 的 A 类 变量 x 在类构造函数中设置 A x 77 我们想将 x 发布到其他线程 考虑以下 3 种变量 x 线程安全 发布的情况 1 x is final 2 x is volatile 3 x 设定为同步块 sy
  • 如何访问JAR文件中的Maven资源? [复制]

    这个问题在这里已经有答案了 我有一个使用 Maven 构建的 Java 应用程序 我有一个资源文件夹com pkg resources 我需要从中访问文件 例如directory txt 我一直在查看各种教程和其他答案 但似乎没有一个对我有
  • logcat 中 mSecurityInputMethodService 为 null

    我写了一点android应显示智能手机当前位置 最后已知位置 的应用程序 尽管我复制了示例代码 并尝试了其他几种解决方案 但似乎每次都有相同的错误 我的应用程序由一个按钮组成 按下按钮应该log经度和纬度 但仅对数 mSecurityInp
  • 关键字“table”附近的语法不正确,无法提取结果集

    我使用 SQL Server 创建了一个项目 其中包含以下文件 UserDAO java public class UserDAO private static SessionFactory sessionFactory static se
  • Cucumber 0.4.3 (cuke4duke) 与 java + maven gem 问题

    我最近开始为 Cucumber 安装一个示例项目 并尝试使用 maven java 运行它 我遵循了这个指南 http www goodercode com wp using cucumber tests with maven and ja
  • 非 Spring 托管类中 DI 的编译时编织

    我想为标记为的类配置编译时编织 Configurable注释能够将 spring 依赖项注入到初始化的类中new操作员 我不想使用加载时编织 因为我无权访问应用程序服务器的运行脚本 因此无法修改它 另外 我希望能够在测试中使用此类 我的意思
  • 干净构建 Java 命令行

    我正在使用命令行编译使用 eclipse 编写的项目 如下所示 javac file java 然后运行 java file args here 我将如何运行干净的构建或编译 每当我重新编译时 除非删除所有内容 否则更改不会受到影响 cla
  • 包 javax.el 不存在

    我正在使用 jre6 eclipse 并导入 javax el 错误 包 javax el 不存在 javac 导入 javax el 过来 这不应该是java的一部分吗 谁能告诉我为什么会这样 谢谢 米 EL 统一表达语言 是 Java
  • 使用反射覆盖最终静态字段是否有限制?

    在我的一些单元测试中 我在最终静态字段上的反射中遇到了奇怪的行为 下面是说明我的问题的示例 我有一个基本的 Singleton 类 其中包含一个 Integer public class BasicHolder private static
  • CamcorderProfile.videoCodec 返回错误值

    根据docs https developer android com reference android media CamcorderProfile html 您可以使用CamcorderProfile获取设备默认视频编解码格式 然后将其
  • 使用 svn 1.8.x、subclise 1.10 的 m2e-subclipse 连接器在哪里?

    我读到 m2e 的生产商已经停止生产 svn 1 7 以外的任何版本的 m2e 连接器 Tigris 显然已经填补了维护 m2e subclipse 连接器的空缺 Q1 我的问题是 使用 svn 1 8 x 的 eclipse 更新 url
  • Spring Rest 和 Jsonp

    我正在尝试让我的 Spring Rest 控制器返回jsonp但我没有快乐 如果我想返回 json 但我有返回的要求 完全相同的代码可以正常工作jsonp我添加了一个转换器 我在网上找到了用于执行 jsonp 转换的源代码 我正在使用 Sp

随机推荐

  • 在java servlet中处理“多部分/相关”

    在 Jetty 8 下运行的 Servlet 接收以下请求 Header Content Type multipart related boundary example Data example content type text xml
  • Java中如何获取for循环的最后一个值?

    import java util Scanner public class Problem1 public static void main String args input Scanner kb new Scanner System i
  • 访问网站时如何检查自己的会话哈希?

    我有兴趣了解当我访问网站时人们在我的会话和 cookie 中存储了什么 有什么方法可以查看请求之间以及我在 Safari Chrome 或 Firefox 中的页面上时发生的情况吗 在 Firefox 中 您可以使用其他Firebug ht
  • Google Sheets 脚本:按名称引用图表

    我试图在 图表 工作表中创建一个 用户界面 这将允许他们从下拉列表中选择一个图表 然后它将显示在该下拉列表的正下方 最终会有大量图表 可能在另一个 图表数据 表上 所以我的想法是将图表从数据表移动到图表表 来回移动 不确定这是否可以做到 我
  • 有条件调用构造函数[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 假设某个类foo有两个自定义构造函数 例如foo foo bar const and foo foo baz const 根据某些条件调用其中任
  • 我可以从空 std 容器的 front() 得到什么?

    If front 返回一个引用 并且容器是空的 我会得到什么 未定义的引用 这是否意味着我需要检查empty 在每个之前front 你会得到未定义的行为 在调用 front 之前 你需要使用 empty 检查容器是否为空 检查容器是否包含某
  • 下载已上传的 Lambda 函数

    我使用 upload zip 在 AWS Python 中创建了一个 lambda 函数 我丢失了这些文件 需要进行一些更改 有什么方法可以下载该 zip 吗 Yes 导航到您的 lambda 函数设置 在右上角您将有一个名为 的按钮 Ac
  • 与模板类交朋友:编译错误

    我试图使用指向实现惯用语的指针来隐藏我正在使用 Concurrency unbounded buffer 来自 VC 2010 的事实 问题是 我正在使用模板执行此操作 但陷入了编译错误 这是代码 阻塞队列 h pragma once na
  • 如何在 php 中制作访客计数器? [关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 我如何计算
  • 如何多次使用ConsoleCancelEventHandler

    我一直忙于编写一个充当前端的应用程序 它有一个 GUI 可以使用按钮和类似的东西来获取命令行选项 并将它们传递给命令行 exe 它使用应用程序的控制台来显示命令行应用程序的输出 这工作正常 但是当使用 Ctrl C 或尝试关闭控制台窗口时
  • 安装 Realm 后出错:必须首先使用有效主机创建 RPC 会话

    我最近使用以下方式安装了领域 npm i realm S react native link realm 重要编辑仅当从设备调试时才会出现此问题 一切仍然有效 但这一次 当我尝试启用Debug Js Remotely从开发菜单中 我收到错误
  • 在 Ruby 中构建长字符串的简洁方法

    在编写 Ruby 客户端脚本 时 我看到了三种构建更长字符串的方法 包括行结束符 所有这些对我来说 闻起来 都有点难看 有没有更干净 更好的方法 变量递增 if render quote quote Now that there is th
  • 项目生成的nuget包依赖于另一个不创建nuget包的项目

    如果我有一个构建 nuget 包的项目 P1 并且让它依赖于一个不构建 nuget 包的项目 P2 则生成的包仍将引用 P2作为 nuget 包 重现步骤 使用 2 个 C 项目 P1 和 P2 创建解决方案 使P1依赖于P2 将以下行添加
  • 使用 JMH 计算指标

    如何计算 JMH 中的 CPU 时间和内存量 例如 我有 代码 State Scope Thread BenchmarkMode Mode All public class JMHSample My int x 1 int y 2 Gene
  • Spring MVC Controller中JsonView的动态选择

    我知道可以用注释控制器方法 JsonView 在 Spring MVC 中静态定义单个视图类 不幸的是 这意味着我可能拥有的每种类型的视图都需要不同的端点 我看到其他人也问过这个问题before https stackoverflow co
  • 为什么在将 Marshmallow 与 SQLAlchemy 自动映射一起使用时出现“Decimal 类型的对象不可 JSON 序列化”?

    Using automap base from sqlalchemy ext automap映射我的桌子 不能够shema dumps result getting raise TypeError f Object of type o cl
  • 使用 HTML5 文件输入时单击按钮从多个文件上传器中删除文件

    如何添加remove这里的按钮就像简单地在文件队列中一一删除一样 我之所以不使用带有 OOB 插件的免费文件上传插件 是因为我的客户要求是出于安全目的 他们需要简单的上传 ui 而不需要任何复杂的插件 function var dropZo
  • 如何描述关系数据库的性能问题?

    我有一个查询在运行关系型数据库这不能满足用户的期望 我应该提供哪些信息以及应该避免哪些信息 以便我能够在该网站上获得有效的帮助 For 甲骨文数据库提供以下信息 描述问题的症状 描述导致问题的行为 查询的行为是否稳定或者问题是否仅发生 有时
  • 预先投影的几何图形 v 让浏览器执行此操作(又名效率 v 灵活性)

    为了提高在线地图的性能 特别是在智能手机上 我遵循 Mike Bostock 的建议 在将其上传到服务器之前尽可能多地准备地理数据 按照他的命令行制图 https medium com mbostock command line carto
  • Log4j Logger.getLogger(Class) 在与 jMockit 和 Cobertura 一起运行时抛出 NPE

    我发现 cobertura maven plugin 2 6 和 jmockit 1 8 之间存在奇怪的交互 我们的生产代码中的一个特定模式有一个带有许多静态方法的类 这些静态方法有效地包装了一个像单例一样的不同类 为这些类编写单元测试进展