PowerMock testing - set static field of class

JunitStaticMockingPowermock

Junit Problem Overview


I'm having difficulty finding a way to set a static field of a class. It's basically like this:

public class Foo{
    // ...
    private static B b = null;
}

where B is another class.

Is there any way to do this in PowerMock other than with setInternalStateFromContext()? Using the context class method seems a bit of overkill for setting one field.

Thanks.

Junit Solutions


Solution 1 - Junit

Whitebox.setInternalState(Foo.class, b);

Works as long as you set a non-null value, and if theres only one field with the class of B. If you can't rely on that luxury, you have to provide the field-name and cast the null to the type you want to set. In that case you would need to write something like this:

 Whitebox.setInternalState( Foo.class, "b", (B)null );

Solution 2 - Junit

Try this:

@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));

Don't work for primitives and primitives wrappers.

Solution 3 - Junit

You simply do:

Whitebox.setInternalState(Foo.class, b);

where b is the instance of B that you want to set.

Solution 4 - Junit

here I am going to set value for "android.os.Build.VERSION.RELEASE", where VERSION is the class name and RELEASE is the final static string value.

> If the underlying field is final, the method throws an > IllegalAccessException unless setAccessible(true) has succeeded for > this field and this field is non-static, NoSuchFieldException needs to be added when you use field.set() method

@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");
 }
}

now the value of String RELEASE will return "Marshmallow".

Solution 5 - Junit

Whitebox.setInternalState(Foo.class, "FIELD_NAME", "value");

Solution 6 - Junit

You can use getAllStaticFields and try to set them

Example:

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);
			}		}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionCraig AndersonView Question on Stackoverflow
Solution 1 - JunitcproingerView Answer on Stackoverflow
Solution 2 - JunitMarcin StachniukView Answer on Stackoverflow
Solution 3 - JunitJohanView Answer on Stackoverflow
Solution 4 - Junitanand krishView Answer on Stackoverflow
Solution 5 - JunitkrekerView Answer on Stackoverflow
Solution 6 - JunitTomasz PrzybylskiView Answer on Stackoverflow