Search code examples
javaunit-testingmockitooption-typepowermockito

PowerMockito.mockStatic() but still getting NPE when static method is called


NOTE - I've marked 3 LINE numbers which I discuss in my question, you may need to scroll to the right in the code snippets to see.

I'm really struggling unit testing a method with chained Optional.map()s.

@Override
public void accept(Object message)
{
    extractSenderReference(message.toString())
        .map(t ->
        {
            t.setTransactionStatus("TAG1"); //  <- LINE #1
            return t;
        })
        .map(StaticConverter::convert) //< -LINE #2
        .ifPresent(Persist::persist);
}

Where extractSenderReference() returns an Optional of type Obj and is a private method.

And my test:

@RunWith(PowerMockRunner.class)
@PrepareForTest({ClassBeingTested.class, StaticConverter.class})

public class MyTest {

private ClassBeingTested updateProcessor = PowerMockito.spy(new ClassBeingTested());
private StatusDataObj statusDataObj = mock(StatusDataObj.class);

@Test
public void testSomething() throws Exception{
    Obj myObj = getObj();
    PowerMockito.mockStatic(StaticConverter.class);

    PowerMockito.doReturn(Optional.ofNullable(myObj)).when(updateProcessor, "extractSenderReference", anyString()); // <- LINE #3
    when(StaticConverter.convert(myObj)).thenReturn(statusDataObj);
    updateProcessor.accept("MESSAGE1");
}

private Obj getObj(){
    Obj obj = new Obj();
    obj.setId(100L);
    return obj;
 }
}

At LINE #1, as marked in my accept() method, object t has been processed and has had its transactionStatus set successfully. However at LINE #2 I am getting a NPE when running the above test.

I've also tried PowerMockito.spy(StaticConverter.class); instead of PowerMockito.mockStatic(StaticConverter.class); as per https://github.com/powermock/powermock/wiki/Mockito#mocking-static-method but I'm getting the same NPE.

My thinking was map is converting t to StatusDataObj type. So when map calls convert, I'll stub and return my type. However, originally I was expecting that LINE #3 would effectively take care of the chained map calls on the Optional returned from extractSenderReference(), since I'm using a real object with values set, but there must be a null value somewhere else?


Solution

  • Persist was null. I'm not sure why the NPE was at LINE 2.