当前位置: 首页 > 知识库问答 >
问题:

我做错了什么,用mockito和反射来嘲笑这个私有的静态最终变量?

闻人越
2023-03-14

我试图测试下面的类,它调用一个单例,通过模仿它来初始化私有静态最终变量,如下所示。

这就是我要做的

public class ClassToTest {

private static final boolean CONF_FLAG = Configuration.getConfig()
.get(Status.Initialization).getConfFlag(); // throws an NPE

public methodToTest(TestObject a){
...
 }
}

其中状态是一个枚举。

测试等级:

public class TestClassToTest{

 TestObject a; 
 ClassToTest t;
    @Before
public void setUp() throws Exception {
     setFinalStatic(ClassToTest.class.getDeclaredField("CONF_FLAG"), true);// this fails!
    a = mock(TestObject.class);
    t =  new ClassToTest();
}
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);
}

}

我不在乎CONF_FLAG的值,但似乎无法嘲弄它。我做错了什么?

共有2个答案

阙繁
2023-03-14

TestClassToTest中的代码看起来不错,但是正在访问ClassToTest。班getDeclaredField(“CONF#u FLAG”)将初始化静态finalClassToTest\CONF#u FLAG字段,您可以在NullPointerException中指示结果。

我假设您不能在ClassToTest中修改源代码。作为修复,您是否可以在setUp()中执行任何其他操作来初始化配置单例,例如使用其公共API方法,以便配置。getConfig()。获取(Status.Initialization)。getConfFlag()调用成功吗?

如果是这样,您可以采用这种方法为测试准备配置对象,而不是使用反射。

邓欣德
2023-03-14

加载类时,将调用此行

private static final boolean CONF_FLAG = Configuration.getConfig().get(Status.Initialization).getConfFlag(); 

因此,为了解决这个问题,我建议使用PowerMock。

使用PowerMock,您可以轻松跳过不必要的行为,方法是使用@SuppressStatic InitilzationFor

此外,您还可以轻松设置内部状态:

Whitebox.setInternalState(ClassToTest.class, "CONF_FLAG", true)

当然,如果你能添加一个新的库,它会起作用。

 类似资料:
  • 问题内容: 基于使用Java反射更改私有静态最终字段,我尝试设置私有静态最终字段。 (我知道这非常骇人,但是这个问题与代码质量无关;与Java反射有关。) 此打印 我已经使用OpenJDK 6和7,以及Oracle 7进行了尝试。 我不知道Java反射可以提供什么保证。但是,如果失败了,我以为会有一个(实际上所有反射方法都会抛出异常)。 这是怎么回事 问题答案: Java内联字段可在编译时初始化为

  • 问题内容: 请参考下面的代码。运行代码时,我可以更改最终非静态变量的值。但是,如果我尝试更改最终静态变量的值,则会抛出异常。 我的问题是,为什么在非静态最终变量也不会抛出异常,反之亦然。为什么会有所不同? 问题答案: 该解决方案并非没有缺点,它可能无法在所有情况下都有效: 如果在字段声明中将字段初始化为编译时常量,则对该字段的更改可能不可见,因为该最终字段的使用会在编译时用编译时常量替换。 另一个

  • 问题内容: 我有一堂课,但不幸的是,我需要在运行时更改它。 使用反射我得到这个错误: 有什么办法可以改变价值? 问题答案: 假设没有阻止你执行此操作,则可以使用来绕开并重置修饰符以摆脱,并实际上修改字段。 这是一个例子: 假设没有SecurityException抛出,上面的代码将打印出来”Everything is true”。 实际执行的操作如下: 基本boolean值true和falsein

  • 问题内容: 我有一个带有静态变量的Java类 如何使用反射访问对象? (我有字符串。我需要访问该对象。) 问题答案: 访问静态字段的方式与普通字段完全相同,只是不需要将任何参数传递给方法(可以传递null)。 试试这个:

  • 问题内容: 使用Mockito间谍的用例是什么? 在我看来,每个间谍用例都可以使用callRealMethod进行模拟处理。 我可以看到的一个区别是,如果您希望大多数方法调用都是真实的,则可以节省一些代码行以使用模拟与间谍。是这样还是我错过了更大的前景? 问题答案: 答案在文档中: 真正的部分模拟(自1.8.0开始) 最后,在邮件列表上进行了许多内部辩论和讨论之后,Mockito添加了部分模拟支持

  • 使用Java反射更改私有静态final字段 我按照上面链接中的说明使用java反射更改私有静态final字段。我有一个名为“数据”的对象在“data”内部,有一个名为“type”的私有静态最终变量我想将“type”设置为null。这是我的密码。 我试着在Java1.7上用类似的代码来做这件事,结果成功了。但是在Android上运行此代码会产生以下错误:java。lang.NoSuchFieldEx