我在我的项目上运行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)
如何解决此问题?
答案 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?