Search code examples
javaelasticsearchmockitotestngpowermockito

Nullpointer Exception for mocking final method


Getting NullPointerException when trying to mock Aggregations.getAsMap()

I have already tried other different ways by using PowerMockito.doReturn(map).when(aggs).getAsMap() but still facing same issue

@PrepareForTest(Aggregations.class)
public class TestExample extends PowerMockTestCase {

    @Test
    public void testMyMethod() {
        Aggregations aggs = PowerMockito.mock(Aggregations.class);
        Cardinality cardinality = Mockito.mock(Cardinality.class);
        Map<String, Aggregation> map = new HashMap<String, Aggregation>();
        map.put("sample", cardinality);
        Mockito.when(aggs.getAsMap()).thenReturn(map);
    }

}
Mockito.when(aggs.getAsMap()).thenReturn(map);

while debugging aggs value is containing below value

{Aggregations$MockitoMock$485838759@3084} Method threw 'java.lang.NullPointerException' exception. Cannot evaluate org.elasticsearch.search.aggregations.Aggregations$MockitoMock$485838759.toString()

Using testng and below version of jars

powermock-api-mockito-2.0.2.jar

mockito-core-2.23.0.jar


Solution

  • The NullPointerException comes from the invocation of the getAsMap method.

    Using Mockito.doReturn(map).when(aggs).getAsMap(); instead should solve that issue.

    However there seems to be a bug in PowerMockito as writing it like this is not supposed to trigger the invocation of the getAsMap() method (which still happens).

    I suggest you create a bug ticket in their bugtracker for this issue.


    If you enable final mocking for Mockito (see here) running the test is successful.

    @RunWith(MockitoJUnitRunner.class)
    public class TestExample {
    
        @Test
        public void testMyMethod() {
            Aggregations aggs = Mockito.mock(Aggregations.class);
            Cardinality cardinality = Mockito.mock(Cardinality.class);
            Map<String, Aggregation> map = new HashMap<String, Aggregation>();
            map.put("sample", cardinality);
    
            Mockito.doReturn(map).when(aggs).getAsMap();
            Assert.assertEquals(map, aggs.getAsMap());
        }
    }
    

    Another option might be to work with a real Aggregations object instead:

    @Test
    public void testMyMethod() {
    
        Cardinality cardinality = Mockito.mock(Cardinality.class);
        Mockito.when(cardinality.getName()).thenReturn("sample");
    
        List<Aggregation> list = new ArrayList<>();
        list.add(cardinality);
    
        Aggregations aggs = new Aggregations(list);
        Map<String, Aggregation> map = aggs.getAsMap();
    
        Assert.assertEquals(1, map.size());
        Assert.assertEquals(cardinality, map.get("sample"));
    }