通过此测试必须完成的绝对最小模拟是什么?
码:
class PrivateStaticFinal {
private static final Integer variable = 0;
public static Integer method() { return variable + 1; }
}
Run Code Online (Sandbox Code Playgroud)
测试:
@RunWith(PowerMockRunner.class)
@PrepareForTest(PrivateStaticFinal.class)
class PrivateStaticFinalTest {
@Test
public void testMethod() {
//TODO PrivateStaticFinal.variable = 100
assertEquals(PrivateStaticFinal.method(), 101);
}
}
Run Code Online (Sandbox Code Playgroud)
相关:测试类中的Mock私有静态最终变量(没有明确答案)
Wal*_*lls 40
免责声明:经过各种线程的大量搜索,我找到了答案.它可以做到,但一般的共识是它不是很安全,但看到你如何只在单位测试中做这个,我认为你接受这些风险:)
答案不是Mocking,因为大多数Mocking都不允许你进入决赛.答案是更"hacky",当你调用Java时,实际上是在修改私有字段是核心java.lang.reflect.Field
和java.lang.reflect.Modifier
类(反射).看看这个答案,我能够把剩下的测试拼凑在一起,而不需要嘲笑来解决你的问题.
这个答案的问题是我NoSuchFieldException
在尝试修改时遇到的问题variable
.对此的帮助在另一篇关于如何访问私有而非公开的领域的帖子中.
反射/场操作说明:
由于Mocking无法处理最终结果,而我们最终做的就是攻击该领域本身的根源.当我们使用Field
操作(反射)时,我们正在寻找类/对象内的特定变量.一旦Java的发现它,我们得到了它的"调节剂",它告诉哪些限制/规则,它有一个像变量final
,static
,private
,public
,等我们找到合适的变量,然后告诉代码,它是可访问的,让我们改变这些修饰语.一旦我们改变了根目录的"访问"以允许我们操纵它,我们就会切换它的"最终"部分.然后,我们可以更改值并将其设置为我们需要的任何值.
简而言之,我们正在修改变量以允许我们更改其属性,删除属性final
,然后更改值,因为它不再存在final
.有关这方面的更多信息,请查看该想法来自的帖子.
所以我们一步一步地传递我们想要操作的变量并且......
// Mark the field as public so we can toy with it
field.setAccessible(true);
// Get the Modifiers for the Fields
Field modifiersField = Field.class.getDeclaredField("modifiers");
// Allow us to change the modifiers
modifiersField.setAccessible(true);
// Remove final modifier from field by blanking out the bit that says "FINAL" in the Modifiers
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
// Set new value
field.set(null, newValue);
Run Code Online (Sandbox Code Playgroud)
将这一切结合到一个新的SUPER ANSWER中.
@RunWith(PowerMockRunner.class)
@PrepareForTest()
class PrivateStaticFinalTest {
@Test
public void testMethod(){
try {
setFinalStatic(PrivateStaticFinal.class.getDeclaredField("variable"), Integer.valueOf(100));
}
catch (SecurityException e) {fail();}
catch (NoSuchFieldException e) {fail();}
catch (Exception e) {fail();}
assertEquals(PrivateStaticFinal.method(), Integer.valueOf(101));
}
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);
}
}
Run Code Online (Sandbox Code Playgroud)
更新 上述解决方案仅适用于在静态块中初始化的常量.当同时声明和初始化常量时,编译器可能会对其进行内联,此时将忽略对原始值的任何更改.
归档时间: |
|
查看次数: |
29157 次 |
最近记录: |