我很难找到一种方法来设置类的静态字段。基本上是这样的:
public class Foo{
// ...
private static B b = null;
}
其中 B 是另一个类。
除了 with 之外,还有什么方法可以在 PowerMock 中做到这一点setInternalStateFromContext()
?使用上下文类方法设置一个字段似乎有点矫枉过正。
谢谢。
Whitebox.setInternalState(Foo.class, b);
只要您设置了一个非空值,并且只有一个字段的类为B
. 如果您不能依赖这种奢侈,则必须提供字段名称并将其null
转换为您要设置的类型。在这种情况下,您需要编写如下内容:
Whitebox.setInternalState( Foo.class, "b", (B)null );
尝试这个:
@RunWith(PowerMockRunner.class)
@PrepareForTest({Foo.class})
public class FooTest {
@Test
public void shouldMockPrivateStaticField() throws IllegalAccessException {
// given
Foo foo = new Foo();
Field field = PowerMockito.field(Foo.class, "b");
field.set(Foo.class, mock(B.class));
不适用于基元和基元包装器。
你只需这样做:
Whitebox.setInternalState(Foo.class, b);
其中 b 是您要设置的 B 的实例。
在这里,我将为“android.os.Build.VERSION.RELEASE”设置值,其中 VERSION 是类名,RELEASE 是最终的静态字符串值。
如果底层字段是final,则该方法抛出IllegalAccessException ,除非该字段的 setAccessible(true)成功并且该字段是非静态的,使用field.set ()方法时需要添加NoSuchFieldException
@RunWith(PowerMockRunner.class)
@PrepareForTest({Build.VERSION.class})
public class RuntimePermissionUtilsTest {
@Test
public void hasStoragePermissions() throws IllegalAccessException, NoSuchFieldException {
Field field = Build.VERSION.class.getField("RELEASE");
field.setAccessible(true);
field.set(null,"Marshmallow");
}
}
现在 String RELEASE的值将返回“ Marshmallow ”。
Whitebox.setInternalState(Foo.class, "FIELD_NAME", "value");
您可以使用getAllStaticFields
并尝试设置它们
例子:
YourFieldClass newValue;
final Set<Field> fields = Whitebox.getAllStaticFields(YourClass.class);
for (final Field field : fields) {
if (YourFieldClass.class.equals(field.getType())) { // or check by field name
field.setAccessible(true);
field.set(YourClass.class, newValue);
} }