Java 当执行 jacoco prepare agent 时,用反射捕获注释将不起作用

Java annotation capturing with reflection will not work when execuete jacoco prepare agent

我有一个多模块 Maven 项目。这有一组由 jaxb 使用 xsd 生成的 classes。下面给出了此类 class 的示例。 (没有 getter 和 setter)

@XmlRootElement(name = "IPPAMUser")
public class IPPAMUser {

@XmlElement(name = "UserName", required = true)
protected String userName;
@XmlElement(name = "PAMInstanceID", required = true)
protected String pamInstanceID;
@XmlElement(name = "Product", required = true)
protected String product;
@XmlElement(name = "Password", required = true)
protected String password;
@XmlElement(name = "PasswordAlogo", required = true)
protected String passwordAlogo;
@XmlElement(name = "LastUpdatedOn", required = true)
protected String lastUpdatedOn;
@XmlElement(name = "IsGenerated")
protected boolean isGenerated;
@XmlElement(name = "LastNotifiedOn", required = true)
protected String lastNotifiedOn;
}

一个模块需要它们作为键值对。因此,一种使用反射编写的方法将它们转换为键值对列表。在该字段中,名称用作键,值用作其值。取值如下。

Field[] fields = t.getClass().getDeclaredFields();
    for(Field field : fields) {
        Annotation anotation = field.getAnnotation(XmlElement.class);
        XmlElement xmlElement = (XmlElement) anotation;

        String methodName;
        String parameterValue = "";
        if(field.getType() == boolean.class){
            methodName = "is" + xmlElement.name();
        } else {
            methodName = "get" + xmlElement.name();
        }
        try {
            Method method = t.getClass().getDeclaredMethod(methodName);
            if(method.invoke(t) == null){
                continue;
            }
            parameterValue = method.invoke(t).toString();
        } catch (NoSuchMethodException e) {
            log.error("Method not found. Method : " + methodName, e);
            log.error("Stack trace : {}", AuthUtils.getPrintableStackTrace(e));
        } catch (InvocationTargetException e) {
            log.error("Method invoking failed. Method : " + methodName, e);
            log.error("Stack trace : {}", AuthUtils.getPrintableStackTrace(e));
        } catch (IllegalAccessException e) {
            log.error("Illegal access " + e);
            log.error("Stack trace : {}", AuthUtils.getPrintableStackTrace(e));
        }
  }

有一些测试用例使用了这种转换。它们工作正常并使用 maven build 执行。为了进行代码覆盖,添加了 jacoco-maven-plugin。当 运行 时,它不会生成 jacoco.exec 文件。根据此 post 执行目标已添加到我的 pom 文件中。之后我的单元测试失败并给出空指针异常。根据堆栈跟踪,它是在执行 "xmlElement.name()" 时引起的,这意味着 xmlElement 为空。所以添加这个执行目标后反射无法获取注解

我如何解决这个问题并使用 jacoco 或任何其他方式获取代码覆盖率报告。

提前致谢。

我自己想出解决办法。当 jacoco 准备代理时,它包含一些合成字段 类。因此,当它尝试获取它时,没有所需注释的合成字段包含在字段列表中。

作为反射检查中的最佳实践,请为您访问的每个字段检查 isSynthetic()。这将避免您访问编译器添加的字段以及 jacoco 等工具。请参阅这些 link 以获得更多参考。

synthetic field Jacoco synthetic field