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