使用反射改变静态最终File.separatorChar单元测试? [英] Using reflection to change static final File.separatorChar for unit testing?

查看:169
本文介绍了使用反射改变静态最终File.separatorChar单元测试?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

具体来说,我试图为需要使用 File.separatorChar 的方法创建一个单元测试,以在windows和unix上构建路径。代码必须在两个平台上运行,但是当我试图改变这个静态最终字段时,我得到了JUnit的错误。



任何人有任何想法是怎么回事? p>

  Field field = java.io.File.class.getDeclaredField(separatorChar); 
field.setAccessible(true);
field.setChar(java.io.File.class,'/');

当我这样做的时候,我得到了

  IllegalAccessException:无法将静态最终字符字段设置为java.io.File.separatorChar为java.lang.Character 

想法?

解决方案

Field.set
$ b


如果底层字段是final的,则方法抛出一个 IllegalAccessException ,除非 setAccessible(true)成功了这个字段,并且这个字段是非静态的

所以起初看起来你运气不好,因为 File.separatorChar static 。令人惊讶的是, 是解决这个问题的一种方法:只需使 static 字段不再为 final

我改编了这个解决方案 from javaspecialist.eu

$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ b field.setAccessible(true);

//从字段
中删除最终修饰符字段modifiersField = Field.class.getDeclaredField(modifiers);
modifiersField.setAccessible(true);
modifiersField.setInt(field,field.getModifiers()&〜Modifier.FINAL);

field.set(null,newValue);
}

我测试过了,它可以工作:

  setFinalStatic(File.class.getField(separatorChar),'#'); 
System.out.println(File.separatorChar); //打印#






请谨慎使用此技术。抛开破坏性的后果,以下实际工作:

pre $ setFinalStatic(Boolean.class.getField(FALSE),true);
System.out.format(Everything is%s,false); //一切都是真实的






重要更新:上述解决方案不适用于所有情况。如果该字段在被重置之前通过Reflection访问并读取,则会抛出 IllegalAccessException 。由于Reflection API创建缓存并重用的内部 FieldAccessor 对象(请参阅java.lang.reflect.Field#acquireFieldAccessor(boolean)实现),所以失败。
示例测试代码失败:

 字段f = File.class.getField(separatorChar); f.setAccessible(真); f.get(NULL); 
//像以前一样调用setFinalStatic:throws IllegalAccessException


Specifically, I'm trying to create a unit test for a method which requires uses File.separatorChar to build paths on windows and unix. The code must run on both platforms, and yet I get errors with JUnit when I attempt to change this static final field.

Anyone have any idea what's going on?

Field field = java.io.File.class.getDeclaredField( "separatorChar" );
field.setAccessible(true);
field.setChar(java.io.File.class,'/');

When I do this, I get

IllegalAccessException: Can not set static final char field java.io.File.separatorChar to java.lang.Character

Thoughts?

解决方案

From the documentation for Field.set:

If the underlying field is final, the method throws an IllegalAccessException unless setAccessible(true) has succeeded for this field and this field is non-static.

So at first it seems that you are out of luck, since File.separatorChar is static. Surprisingly, there is a way to get around this: simply make the static field no longer final through reflection.

I adapted this solution from javaspecialist.eu:

static void setFinalStatic(Field field, Object newValue) throws Exception {
    field.setAccessible(true);

    // remove final modifier from field
    Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);

    field.set(null, newValue);
}

I've tested it and it works:

setFinalStatic(File.class.getField("separatorChar"), '#');
System.out.println(File.separatorChar); // prints "#"


Do exercise extreme caution with this technique. Devastating consequences aside, the following actually works:

setFinalStatic(Boolean.class.getField("FALSE"), true);
System.out.format("Everything is %s", false); // "Everything is true"


Important update: the above solution does not work in all cases. If the field is made accessible and read through Reflection before it gets reset, an IllegalAccessException is thrown. It fails because the Reflection API creates internal FieldAccessor objects which are cached and reused (see the java.lang.reflect.Field#acquireFieldAccessor(boolean) implementation). Example test code which fails:

Field f = File.class.getField("separatorChar"); f.setAccessible(true); f.get(null);
// call setFinalStatic as before: throws IllegalAccessException

这篇关于使用反射改变静态最终File.separatorChar单元测试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆