Sunny
Sunny

Reputation: 928

JUnit testing using powerMockito is giving NPE

I Have a class for which i want to write a Junit unit test case.

public class ComparatorUtil {

    public static Map<String, ValueDifference<Object>> compareJsonObject(Object srcObject, Object targetObject)
                throws JsonGenerationException, JsonMappingException, IOException {
        String initialJson = ConverterUtil.convertObjectToJson(srcObject);
        String updatedJson = ConverterUtil.convertObjectToJson(targetObject);
        Gson g = new Gson();
        Type mapType = new TypeToken<Map<String, Object>>(){}.getType();
        Map<String, Object> firstMap = g.fromJson(initialJson, mapType);
        Map<String, Object> secondMap = g.fromJson(updatedJson, mapType);
        Map<String, MapDifference.ValueDifference<Object>> diffMap = Maps.difference(firstMap, secondMap).entriesDiffering();
        return diffMap;
    }
}


public class ConverterUtil {

    public static String convertObjectToJson(Object o)
            throws JsonGenerationException, JsonMappingException, IOException {
        ObjectMapper mapperObj = new ObjectMapper();
        return mapperObj.writeValueAsString(o);
    }
}

Junit test case written by me:-

@RunWith(PowerMockRunner.class)
@PrepareForTest(ConverterUtil.class)
public class ComparatorUtilTest {

    @Before
    public void setUp() {
        PowerMockito.mockStatic(ConverterUtil.class);
    }

    @Test
    public void testValueDiff() throws JsonGenerationException, JsonMappingException, IOException {
        TestObject srcObject = new TestObject();
        srcObject.setColor("white");
        srcObject.setId(1);
        TestObject targetObj = new TestObject();
        targetObj.setColor("white");
        targetObj.setId(1);
        targetObj.setSuffix("AA");
        ComparatorUtil.compareJsonObject(srcObject, targetObj);
        PowerMockito.verifyStatic(VerificationModeFactory.times(2));
        ConverterUtil.convertObjectToJson(srcObject);
        ConverterUtil.convertObjectToJson(targetObj);
    }
}

When I am running the test class, I am getting a Null Pointer Exception as the initialJson and updatedJson is coming to be null. Can anyone please tell me where am I doing wrong?

Upvotes: 1

Views: 154

Answers (1)

GhostCat
GhostCat

Reputation: 140427

So many things so wrong here.

  • You seem to assume how to use PowerMock. But what you put together simply doesn't make sense! You need to create a mocking specification using 'when().thenReturn()' for example.
  • Meaning: it is not enough to instruct PowerMock that a certain class will be mocked. You have to tell PowerMock about the actual values to be returned when these static methods are invoked.
  • so start by reading a good tutorial top to bottom. Don't use PowerMock for your own code, instead look how a tutorial solves a simple problem.

Then: PowerMock comes at certain cost. So you avoid using it. You rather should step back and look into reworking your code so that it can be tested without the need to mock static methods. You see, we are talking about code that transforms some input into some output. You should be able to write production and test code that requires no mocking at all for such situations. If at all, you should use frameworks such as Mockito - good production code can be tested without PowerMock.

More specifically: why is there a need to mock the static method? That seems to indicate that your ObjectMapper doesn't work in your unit test setup. It starts right there!

You see, a good unit test for your conversion method should simply look like:

assertThat(someConverterUnderTest.convert(fineTunedInput), is(expectedOutput));

That's it! You should design your converter to fully work in your unit test environment. And then all need for mocks is gone. In other words: you are currently testing implementation details. Instead you should always try testing the public contract of your methods. Testing implementation details is sometimes unavoidable, but as written before: the code you are showing here should really really be tested without mocks.

Then: even when you need mocks: the static methods are getting in your way. That is a clear signal that you shouldn't be using static here! Instead, you turn those elements that might require mocking either into parameters or into fields of your classes under test. Because then you can simply inject mocked objects. Which means that you don't need the PowerMock(ito) tooling anymore.

Upvotes: 1

Related Questions