如何使用JUnit,EasyMock或PowerMock模拟静态最终变量

Pri*_*nce 25 java junit unit-testing easymock powermock

我想嘲笑使用JUnit,EasyMock的或PowerMock静态final变量以及模拟一个国际化类.我怎么做?

Ant*_*ine 43

嘲弄变量的东西吗?我会称之为重新分配.我不认为EasyMock或PowerMock会给你一个简单的方法来重新分配一个static final字段(这听起来像一个奇怪的用例).

如果你想这样做,你的设计可能有问题:static final如果你知道变量可能有另一个值,则避免(或更常见的是全局常量),即使是出于测试目的.

无论如何,您可以使用反射来实现(来自:使用反射来更改静态最终的File.separatorChar以进行单元测试?):

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)

使用方法如下:

setFinalStatic(MyClass.class.getField("myField"), "newValue"); // For a String
Run Code Online (Sandbox Code Playgroud)

拆除时不要忘记将字段重置为原始值.

  • 使用它的任何人都应该记住,java编译器可以内联常量,因此代码可能实际上不会访问其他最终字段(应该适用于File.separatorChar,因为内联时常量是无用的).这个在[这个问题]中描述(http://stackoverflow.com/questions/5173372/java-static-final-values-replaced-in-code-when-compiling) (4认同)
  • 此解决方案不适用于最新的 JDK-11 或更高版本。因为在 JDK-11 或 + 的普通版本中不鼓励修改最终变量的值。 (3认同)

cwa*_*ash 5

它可以使用PowerMock功能的组合来完成.使用@PrepareForTest({...})注释进行静态模拟,模拟您的字段(我正在使用Mockito.mock(...),但您可以使用等效的EasyMock构造),然后使用该WhiteBox.setInternalState(...)方法设置您的值.请注意,即使您的变量是,这也会起作用private.

有关扩展示例,请参阅此链接:http://codyaray.com/2012/05/mocking-static-java-util-logger-with-easymocks-powermock-extension