javaelasticsearchpowermock

Unable to mock Aggregations#get method from elasticsearch


I am trying to test a class using elasticsearch aggregation framework and for some reason am unable to mock the get method of the Aggregations object. I have the relevant classes in @PrepareForTest annotation and also have the @Runwith(PowerMockRunner) annotation in the test class.

Any suggestions on what I could change to make it work?

My method under test:


public void aggregation() {
    //prepare aggregation query
    SearchResponse response = client.search(query, RequestOptions.DEFAULT);
    Aggregations aggregations = response.getAggregations(); // mocked aggregations object gets set 
    Terms terms = aggregations.get("field"); //throws NullPointerException
    //use terms object
}

My test method:

@Test 
public void testAggregation() {
    RestHighLevelClient client = PowerMockito.mock(RestHighLevelClient.class);
        testObject.setClient(client);
        SearchResponse response = PowerMockito.mock(SearchResponse.class);
        Aggregations aggregations = PowerMockito.mock(Aggregations.class);
        Terms terms = PowerMockito.mock(Terms.class);
        PowerMockito.when(client.search(any(SearchRequest.class), any(RequestOptions.class))).thenReturn(response);
        PowerMockito.when(response.getAggregations()).thenReturn(aggregations); 
        PowerMockito.when(aggregations.get(anyString())).thenReturn(terms); // aggregations.get("field") throws NullPointerException
    testObject.aggregation();
}

Stack trace:

"org.elasticsearch.search.aggregations.Aggregations.equals(Aggregations.java:106)"
"org.mockito.internal.invocation.InvocationMatcher.matches(InvocationMatcher.java:61)"
"org.mockito.internal.stubbing.InvocationContainerImpl.findAnswerFor(InvocationContainerImpl.java:79)"
"org.mockito.internal.handler.MockHandlerImpl.handle(MockHandlerImpl.java:87)"
"org.powermock.api.mockito.internal.invocation.MockitoMethodInvocationControl.performIntercept(MockitoMethodInvocationControl.java:244)"
"org.powermock.api.mockito.internal.invocation.MockitoMethodInvocationControl.invoke(MockitoMethodInvocationControl.java:196)"
"org.powermock.core.MockGateway.doMethodCall(MockGateway.java:182)"
"org.powermock.core.MockGateway.doMethodCall(MockGateway.java:164)"
"org.powermock.core.MockGateway.methodCall(MockGateway.java:134)"
"org.elasticsearch.search.aggregations.Aggregations.get(Aggregations.java)"

Solution

  • I finally ended up not mocking the Aggregations object. Calling the constructor with terms as object took care of what I needed to do. My final code looks something like this:

    @Test 
    public void testAggregation() {
        RestHighLevelClient client = PowerMockito.mock(RestHighLevelClient.class);
            testObject.setClient(client);
            SearchResponse response = PowerMockito.mock(SearchResponse.class);
    
            Terms terms = PowerMockito.mock(Terms.class);
            // mock terms object calls here
            Aggregations aggregations = new Aggregations(terms);
            PowerMockito.when(client.search(any(SearchRequest.class), any(RequestOptions.class))).thenReturn(response);
            PowerMockito.when(response.getAggregations()).thenReturn(aggregations); 
            testObject.aggregation();
    }