2

So I'm writing java unit tests (mockito) for a class that builds elasticsearch queries. The current way it's being done is quite sloppy, it's such tedious work to update the tests whenever a change is made. Unfortunately, it appears the official ES documentation for java testing is dead, so I'm hoping someone out there has some advice as to how my tests can be better written.

The source class is a rather complex Query, and the unit tests are essentially building an instance of the class and serializing it to a JsonNode. Then the JsonNode is traversed and the expected value is asserted. It seems this style of testing is borderline hardcode. Here's an example of a test:

@Test
public void toQueryBuilder_initialQuery() {
  // queryValue defined here.
  JsonNode result = QueryBuilderSerialization.toJsonNode(new QueryConstraintA(queryValue)
                                             .toQueryBuilder());
  // assert expected queries
  assertEquals(EXPECTED_MIN, result
            .get("bool")
            .get("filter").get(0)
            .get("function_score")
            .get("min_score")
            .asInt());

  assertEquals(EXPECTED_LOWER_BOUND, countQuery.get(7)
            .get("function_score")
            .get("query")
            .get("nested")
            .get("query")
            .get("constant_score")
            .get("filter")
            .get("bool")
            .get("filter").get(0)
            .get("bool")
            .get("filter").get(0)
            .get("bool")
            .get("should").get(0)
            .get("range")
            .get(RANGE_FIELD_NAME)
            .get("from")
            .asInt());
}

There's roughly 1000 lines of tests written in this style, in just this file alone. So you can imagine how much of a pain it is when you modify the source query. Does anyone have a suggestion as to how this can be better done? Thanks in advance for any time put into this.

1 Answer 1

1

I do not recommend writing these kind of tests. Instead of testing that the query looks OK, what you really want to test is that it returns a correct output when it runs. It's a lot more work, but in our shop we run the actual queries against a local Docker instance of Elasticsearch. This checks that the queries aren't malformed and that they really do what they are supposed to. It also makes them more resilient when someone refactors the query (to improve latency), without making any changes to the logic.

Sign up to request clarification or add additional context in comments.

2 Comments

I kind of want to do an integration test but I really don't want to run a local Docker instance on a build server, not really the best solution hardware considered. It's been a year since your post, found any other good solutions to test a client?
Not really :) I still think a local ES docker is the way to go. Another option is having a small development ES server up somewhere. In the test setup, generate an index with a random name, put some data in it, and delete it in the teardown. Since the tests names are random, you run have multiple people running an they won't conflict with each other. However, if the dev ES server is down, CI will be broken for everyone, which is why I prefer the local docker option.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.