cobertura没有通过反射测试课程

时间:2015-12-01 10:36:03

标签: java maven cobertura

我在我的项目上运行mvn clean cobertura:cobertura install,但其中一项测试失败。

测试尝试使用由反射编写的构建器来访问类。

public MyClass(Builder builder) throws Exception {
    Field[] classFields = MyClass.class.getDeclaredFields();
    Field[] classBuilderFields = Builder.class.getDeclaredFields();
    for (int i = 0; i < classBuilderFields.length; i++) {
        Field fieldInClass = classFields[i];
        Field fieldInBuilder = classBuilderFields[i];
        fieldInBuilder.setAccessible(true);
        String fieldNameInClass = fieldInClass.getName();
        String fieldNameInBuilder = fieldInBuilder.getName();
        if (null != fieldNameInClass && null != fieldNameInBuilder && fieldNameInClass.equals(fieldNameInBuilder)) {
            fieldInClass.set(this, fieldInBuilder.get(builder));
        } else {
            throw new Exception("");
        }
    }
}

我调试了代码,并在我的班级 __ cobertura_counters 中看到 cobertura “实施”了它自己的变量。这是一个例外:

java.lang.IllegalAccessException: Can not set static final [I field com.domain.MyClass.__cobertura_counters to
    at sun.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:73)
    at sun.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:77)
    at sun.reflect.UnsafeQualifiedStaticObjectFieldAccessorImpl.set(UnsafeQualifiedStaticObjectFieldAccessorImpl.java:77)
    at java.lang.reflect.Field.set(Field.java:741)
    at com.domain.MyClass.<init>(MyClass.java:217)
    at com.domain.MyClassTest.setUp(MyClassTest.java:57)
    at com.domain.MyClass$Builder.build(MyClass.java:197)

如何解决此问题?

2 个答案:

答案 0 :(得分:3)

确实如此,Cobertura添加了这个字段,因此它可以跟踪访问的代码。其他代码覆盖工具添加类似的字段,用于类似目的。生成的字段具有以下签名:

public static final transient int[] __cobertura_counters;

您可以做的只是忽略代码中的瞬态字段。你可以这样做:

if (!Modifier.isTransient(fieldInClass.getModifiers())) {
    // do a thing
}

但请注意,非生成代码也可能包含瞬态字段,因此根据您要反映的代码,这可能是也可能不是选项。否则,您唯一的选择(AFAIK)就是检查fieldInClass.getName().equals("__cobertura_counters")

通常,编译器生成的字段将标记为&#34;合成&#34;。例如,javac为非静态内部类生成的this$0字段是合成的。检查它很容易:fieldInClass.isSynthetic()。但是,出于某种原因,Cobertura并没有遵循这一惯例。

答案 1 :(得分:-1)

问题是,您尝试修改的字段是最终的。可以删除最终修饰符,并且可以完成。 polygenelubricants发布了一段很好的代码,可用于删除修饰符。您可以在此处找到它:Using reflection to change static final File.separatorChar for unit testing?