4

How can I control the IndexResponse when using the Elasticsearch async api w/ the HighLevelRestClient v7.5?

Maybe I need to mock the Low Level REST Client and use that mock for my High Level REST Client?

@Test
void whenIndexResponseHasFailuresDoItShouldReturnFalse() {

  // arrange
  var indexResponse = mock(IndexResponse.class);
  when(indexResponse.getResult()).thenReturn(Result.UPDATED);

  var restHighLevelClient = mock(RestHighLevelClient.class);
  when(restHighLevelClient.indexAsync())
      //do something here??

  var indexReqest = new IndexRequest(...);

  //act
  var myHelper = new MyHelper(restHighLevelClient);
  var result = myHelper.doIt(indexReqest)
    .get();

  //assert
  assert(result).isFalse();
}
class MyHelper {

  //injected RestHighLevelClient

  CompletableFuture<Boolean> doIt(Customer customer) {

    var result = new CompletableFuture<Boolean>();
    var indexRequest = new IndexRequest(...);

    restHighLevelClient.indexAsync(indexRequest, RequestOptions.DEFAULT
         , new ActionListener<IndexResponse>() {
      @Override
      public void onResponse(IndexResponse indexResponse) {  //want to control indexResponse
        if (indexResponse.getResult() == Result.UPDATED) {
          result.complete(false);
        } else {
          result.complete(true);
        }
      }

      @Override
      public void onFailure(Exception e) {
        ...
      }
    });

    return result;
  }
}

Update Sample project using Oleg's answer

spottedmahn
  • 14,823
  • 13
  • 108
  • 178
  • Refactor your code. You can't unit test if `RestHighLevelClient` is created in `doIt` – Oleg Feb 25 '20 at 22:57
  • It’s not, I’ll update my question, it’s injected, good point, thanks @Oleg – spottedmahn Feb 25 '20 at 23:16
  • Feel free to ignore this comment and not answer, it doesn't really matter anyway, I'm just curious; why did you accept my answer but didn't upvote it? – Oleg Feb 27 '20 at 01:51
  • Hi @Oleg - I'm experimenting/researching, I've usually accepted and upvoted. [Interesting read](https://meta.stackexchange.com/questions/686/accepting-answer-without-upvoting). Before I upvoted, in this case, I wanted to research "should I accept and upvote or just accept? what's the 'right' way?" – spottedmahn Feb 27 '20 at 12:52

1 Answers1

2

Mock RestHighLevelClient then inside indexAsync mock IndexResponse and pass it to the ActionListener.

RestHighLevelClient restHighLevelClient = mock(RestHighLevelClient.class);
when(restHighLevelClient.indexAsync(any(), any(), any())).then(a -> {
    ActionListener<IndexResponse> listener = a.getArgument(2);
    IndexResponse response = mock(IndexResponse.class);
    when(response.getResult()).then(b -> {
        return Result.UPDATED;
    });
    listener.onResponse(response);
    return null;
});
MyHelper myHelper = new MyHelper(restHighLevelClient);
Boolean result = myHelper.doIt(null).get();
assertFalse(result);

Also, configure Mockito to support mocking final methods otherwise a NPE will be thrown when mocking indexAsync.

Option 1

Instead of using the mockito-core artifact, include the mockito-inline artifact in your project

Option 2

Create a file src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker with mock-maker-inline as the content

spottedmahn
  • 14,823
  • 13
  • 108
  • 178
Oleg
  • 6,124
  • 2
  • 23
  • 40