我很难在类中模拟私有静态final String字段。这是我的java示例代码:
public class Fruit {
private static final String FRUIT = "apple";
public void getFruit() {
System.out.println("I like " + FRUIT);
}
}
我用Mockito来模拟FRUIT变量,这样我就可以将FRUIT的值从“apple”改为“mango”。为此,这是我的测试:
public class FruitTest {
@Test
public void testFruit() throws NoSuchFieldException, SecurityException, Exception {
setFinalStatic(Fruit.class.getDeclaredField("FRUIT"), "mango");
Fruit fruit = new Fruit();
fruit.getFruit();
}
static void setFinalStatic(Field field, Object newValue) throws Exception {
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, newValue);
}
}
我在期待System.out.println("I like " + FRUIT);
它会打印芒果,但它仍在打印苹果。我真的很感激,如果有人能帮我这个只使用MOCKITO而不是PowerMock等。
答案 0 :(得分:0)
编译时常量可以由javac内联进行优化。如果你改变你的Fruit课程:
public static class Fruit { public static final String FRUIT = getFruit();
public static String getFruit() {
return "apple";
}
}
它将显示结果芒果 setFinalStatic(Fruit.class.getField(" FRUIT")," mango"); 的System.out.println(Fruit.FRUIT);
答案 1 :(得分:0)
我最近调查了一些静态字段并且我认为如果没有powermock的帮助你不能做你正在尝试的事情。我也不确定你为什么要这样做。私有静态final字段是一个常量,并且不应该有一个真正的理由为什么你想要一个常量来改变。任何试图这样做的测试都试图测试错误的东西。
答案 2 :(得分:0)
更改常量的值不是一个好习惯。更重要的是,我认为是不可能的。但是,如果要更改字段的值,请删除修饰符“final”。
答案 3 :(得分:0)
单词 final 正好描述了创建String后不应该更改该值。这是您在Java中获取常量的方式。您的getFruit方法将始终返回“apple”。 Mockito对此不会帮助你。如果您正在测试此方法,则需要测试它始终返回“apple”。在你的情况下,方法是静态的是无关紧要的,因为你返回的是一个恒定的值。使用反射不是一个好主意,不仅仅因为它是一个非常糟糕的编码实践,而且因为你没有办法在未来正确管理变更。这是一个需要大量维护的侵入式代码,并且它总是生成几行,只是为了在运行时更改该方法,以便“可以对其进行测试”。总而言之,现实生活中的案例并不需要在单元测试中进行反思,除非当然有充分的理由或仅仅是架构需要改进。反思更像是一种学术性的东西,或者你正在构建自己的注射系统,模拟工具或任何需要这种编码的东西。