I'm trying to set a private static final
field in a class with private
constructor for a JUnit test. When I boil the code down to its basics, I get the following:
public class Foo {
private static final boolean FLAG = false;
private Foo() { /* don't call me */ }
public static boolean get() { return FLAG; }
}
My tests looks like this:
@RunWith(PowerMockRunner.class)
@PrepareEverythingForTest // Whitebox fails without this line
public class FooTest {
@Test
public void testGet() {
Whitebox.setInternalState(Foo.class, "FLAG", true);
assertTrue(Foo.get());
}
}
And here is an excerpt from my POM file:
<junit.version>4.11</junit.version>
<powermock.version>1.5.4</powermock.version>
<mockito.version>1.9.5</mockito.version>
When I put a breakpoint on return FLAG;
, I can clearly see that FLAG
was set to true
in IntelliJ's debugger. Yet the test fails with an AssertionError
.
Any ideas what to do to make this work?
Update: using reflection doesn't seem to work, either:
@Test
public void testGet_usingReflection() throws Exception {
setField(Whitebox.invokeConstructor(Foo.class), "FLAG", true);
assertTrue(Foo.get());
}
public static void setField(Object targetObject, String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException {
Class clazz = targetObject.getClass();
Field field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
Field modifiers = Field.class.getDeclaredField("modifiers");
modifiers.setAccessible(true);
modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(targetObject, value);
}
The setField()
method is one I have available through an internal library. Unfortunately, it produces the same result: AssertionError
Update 2: Getting completely rid of PowerMock doesn't help much, either, apparently:
@Test
public void testGet_usingReflectionWithoutPowerMock() throws Exception {
setField(Foo.class.getDeclaredField("FLAG"), true);
assertTrue(Foo.get());
}
public static void setField(Field field, Object value) throws NoSuchFieldException, IllegalAccessException {
field.setAccessible(true);
Field modifiers = Field.class.getDeclaredField("modifiers");
modifiers.setAccessible(true);
modifiers.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, value);
}
For this, I even removed the PowerMock annotations from the class level...
I've also posted this question to the PowerMock mailing list now.
I had similar thing to test, but the only difference was that my static final variable was an Object
rather than primitive type. And indeed changing boolean
to Boolean
makes it work.
public class Foo {
private static final Boolean FLAG = false;
private Foo() { /* don't call me */ }
public static boolean get() { return FLAG; }
}
Also I would recommend using @PrepareForTest(SomeClass.class)
where SomeClass
has static final field rather than @PrepareEverythingForTest
because if it's big project it may take some time prepare everything.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With