是否可以模拟私有静态最终字符串文字?
Posted
技术标签:
【中文标题】是否可以模拟私有静态最终字符串文字?【英文标题】:Is it possible to mock a private static final String literal? 【发布时间】:2012-10-22 13:26:54 【问题描述】:我对上述问题的猜测是这是不可能的,但我需要确认。所以问题是私有静态最终字符串中有一个Oracle特定的SELECT(使用ROWNUM和FOR UPDATE SKIP LOCKED关键字)。
private static final String REC_QUERY_SELECT = "SELECT * FROM ... WHERE ROWNUM <=1 for update skip locked";
我想用 HSQL 对其进行单元测试,但 HSQL 不知道这些 Oracle 关键字。我想修改 REC_QUERY_SELECT 变量(将 SELECT 修改为更简单的变量),但我不能,因为它是 final 和 String 文字。 有没有办法修改它? (我不能更改代码库,我只需要编写单元测试)。我也试过这段代码:
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, newValue);
【问题讨论】:
你为什么不把你的最终字符串复制到另一个非最终字符串变量中? 编译时已知的常量可以被 javac 编译器内联,所以即使你改变了原来的,它在任何地方都不会改变。 如果您的原始查询需要更改以使用 HSQL 进行测试,那么您正在测试什么? 感谢大家的回复!此 SELECT 位于原始代码库中,该代码库检索一些记录并且正在处理这些实体。我想测试这种处理机制,但不使用 Oracle 数据库。这就是我使用 HSQL 的原因。这就是为什么这个 String 应该被改变的原因。我不允许修改原始代码,因为它已经在生产中。彼得:你有同样的意见是不可能修改的吗?再次感谢! 【参考方案1】:作为编译时常量(参见 JLS),字符串将在编译时复制到调用站点,因此在运行时更改值可能无济于事。
一般来说,您应该在测试中像在生产中一样对待针对不同数据库的处理。相同的旧质量软件工程,通常不涉及反射。
【讨论】:
谢谢汤姆!你的意思是不改变正在测试的代码就无法解决? @Viktor 生成的代码将直接引用字符串值(IIRC,ldc
指令指向类文件中的字符串内容)。该字段未被访问。您需要更改已编译的代码。您可以将静态设置为非编译时常量,但我建议采用更好的方法。【参考方案2】:
使用ASM,您可以就地修改目标类的字节码,并在运行时使用修改后的类。
【讨论】:
哇,到目前为止我还不知道这个框架。这才是真正的重炮! :) 特殊任务需要特殊武器:)以上是关于是否可以模拟私有静态最终字符串文字?的主要内容,如果未能解决你的问题,请参考以下文章