RestHighLevelClient mocking

Hi,

Is there a way to mock the Java client 'RestHighLevelClient' ? Most of the methods are 'final' and can't be overridden.

Thanks for your support.

4 Likes

I don't think you can do that.

À workaround would be to use the client from your own ElasticsearchDao class and mock this one instead.

Would that work?

Hi,

Thanks for the answer.
We already have something similar to a DAO to request ES. THe goal is to test the DAO like behavior to detect issue and regressions.

I understand your point.

But the DAO is just a router to elasticsearch normally, no?
Like it's doing something like (pseudo code):

public List<MyObject> search(String term) {
  SearchResponse response = esClient.search(new SearchRequest()...);
  return MyObject.fromJson(response.toString());
}

There should be barely no intelligence here IMO.
Smart things should be done on a higher level like a Service layer.

Mocking this method is then straight-forward when you want to test your service.

Indeed you can not "unit test" your DAO by itself.
But you can do IT with it if needed.

@javanna has may be more thoughts on that and if there is any plan to make those methods not final.

I'm not fully aligned with your, IMO DAOs can be validated by some unit tests (see DBUnit or similar). For sure, you can still detect some issues during integration tests but I prefer to see the issue before that stage.

It depends on what you call a test.

I mean that if you have a method like:

public void save(Entity e) {
  db.save(e);
}

IMO it's pretty much useless to test that this method actually saves something in a DB if you are mocking the DB.

It's like testing a getter or setter of a Java Bean. Does make a lot of sense to me to test that.

But if your class does something smarter like:

public void save(Entity e) {
  if (db.save(e)) {
   messageQ.send("OK");
  } else {
   messageQ.send("KO");
  }
}

Then that's another story and in that case I would not consider that class as a DAO but as a Service.

I'd love to see what your DAO is doing actually what a typical unit test would look like. Could you share some example?

Hi,

You point your finger on the right topic. Sometimes DAO make transformations, aggregations or else and it can be a good practice to validate the query. For sure it depends on the project and that's an other discussion.

In our case, we make some transformations.

Thanks for your help

Sometimes DAO make transformations, aggregations or else and it can be a good practice to validate the query.

Yeah. But let say you implement something like this:

class MyDao {
  public SearchResponse search(SearchRequest request) {
    return esClient.search(request);
  }

  public SearchRequest buildRequest(QueryBuilder query) {
    return new SearchRequest("person").source(new SearchSourceBuilder()
                                  .query(query)
                                  .aggregation(/* whatever */));
  }
}

Then what you actually want to test is the buildRequest() method right?
Not the fact that this method can be executed correctly against a fake esClient which you wanted to mock, right?

That's only my personal opinion here. Again, I'd like to see what you wrote if you don't mind sharing it as I might be totally wrong with your use case.

Not exactly. Our DAO doesn't expose es objects. It's in charge of building the query and then the request by using some data from our model and logic. But the goal of this topic is not to discuss the conception of our indexing layer, just to get a way to implement unit tests without having an es installed.

Hi,

Even a simple thing as below does not seem to be working when I am trying to test my Service class which is using RestHighLevelClient.index() method.

It internally calls performRequest which gives a null pointer exception. Any ideas how to achieve this?

IndexResponse indexResponse = Mockito.spy(new IndexResponse(new ShardId(new Index("test", "test-uuid"), 1), "testmapping", "1", 1, true));
        indexResponse.setShardInfo(new ReplicationResponse.ShardInfo());
        indexResponse.setForcedRefresh(true);

        Mockito.doReturn(indexResponse).when(restHighLevelClient).index(any());
5 Likes

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.