1

I'm trying to test the following class which calls out to a singleton that initializes a private static final variable by mocking it out, following this example.

Here's what I'm doing

public class ClassToTest {

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

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

where Status is an Enum.

Test class :

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

}

I don't care for the value of CONF_FLAG but cant seem to mock it out. What am I doing wrong?

MuleNoob
  • 127
  • 1
  • 6

2 Answers2

1

Your code in TestClassToTest looks fine, but accessing ClassToTest.class.getDeclaredField("CONF_FLAG") will initialize the static final ClassToTest#CONF_FLAG field, which you indicate results in a NullPointerException.

I'm assuming that you can't modify the source code in ClassToTest. As a fix, is there anything additional that you can do in setUp() to initialize the Configuration singleton, for example using its public API methods, so that the Configuration.getConfig().get(Status.Initialization).getConfFlag() call succeeds?

If so, you can take this approach of preparing the Configuration object for your tests, rather than using reflection.

ck1
  • 5,243
  • 1
  • 21
  • 25
  • +1. To add here, as long as the call happens as part of static field initialization, you will have little control over the timing of the call and will have effectively no opportunity to replace it for tests. As a rule of thumb, if a call is dangerous enough to possibly throw an exception or to warrant mocking in tests, you don't want it in any static initializer. – Jeff Bowman Apr 23 '16 at 03:20
  • @Jeff Bowman,@ck1 Yeah I totally understand the part about not placing it in the static initializer but this is a piece of legacy code that I got slapped with and I'm kinda sorta trying to work my way around it.. Assuming `getConfig()` is a static method.. is there any way I can possibly mock/stub the entire call to the singleton? If yes, Id greatly appreciate some code/pseudocode. – MuleNoob Apr 23 '16 at 05:45
1

When your class is loaded then this line is called

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

So, to resolve the issue I'd like to suggest use PowerMock.

With PowerMock you can easy skip unnecessary behavior by using @SuppressStaticInitilizationFor.

Also, you will be able easy set internal state:

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

Of course, it will work in case if you can add a new library.

Artur Zagretdinov
  • 2,034
  • 13
  • 22