I’m sure there are as many ways to test an application as there are developers, but I’ll try to give you my opinion.
You have to distinguish between two things:
- The business logic of your application, usually implemented in “services”.
- The data access layers of your application, usually implemented in “repositories” (at least in the Spring Data world).
Usually services depend on the data access layer.
When you test your services, it may indeed be a good idea to keep the configuration to a minimum. You can achieve this by mocking your repositories: then, you won’t need Hibernate ORM, Hibernate Search, the database or Elasticsearch.
When you test your repositories, I don’t think mocking is a good idea. A lot of the errors you’re likely to encounter will only be detected by Hibernate ORM, the database, Hibernate Search or Elasticsearch. If you mock them, you won’t see the errors.
Take for example the search DSL of Hibernate Search: Hibernate Search performs validation of the arguments you pass to the predicates, and throws an exception when a argument has an incorrect type, for example. If you mock Hibernate Search, you won’t see that.
Another example: in your Hibernate Search mapping, you are free to reference analyzers with any name, because some analyzers can be defined on the server side in Elasticsearch. Upon startup, Hibernate Search will push the mapping to Elasticsearch, and Elasticsearch will validate that every analyzer referenced in your mapping actually exists. If you mock Elasticsearch, you won’t see invalid analyzer references.
There are many examples like this, and in the end I think it’s much safer to just write integration tests for your repositories, not unit tests. Of course you don’t need to write full-stack integration tests: you can still mock repositories when you test your services. But the repositories, in my opinion, should be tested in an environment as close to your production as possible.
This means spinning up a database, H2 if you must, but ideally the same one you’ll use in production (using a container for example). This also means spinning up an Elasticsearch instance.
There are tools do integrate this to your Maven build, such as the elasticsearch-maven-plugin, and probably other plugins to spin up containers using docker. But if you don’t want any of this, you can also disable the integration tests by default, and only activate them with a specific Maven profile in your continuous integration job (Jenkins, Travis, …) where the database and Elasticsearch are already configured.
Regarding the configuration of the datasource in Spring and the backend in Hibernate Search, I don’t think you will need much. You basically only need to configure the JDBC URL and the Elasticsearch URL; everything else can be included in your core settings as you will need the exact same settings for production and integration tests.
If you’re interested in an example, we have a Spring showcase in the Hibernate Search integration tests: https://github.com/hibernate/hibernate-search/tree/master/integrationtest/showcase/library
This includes a production configuration in
src/main/resources (using environment variables for the bits we don’t want in the source) and the necessary overrides in
However, in our case we only used H2, and we tested the whole application in integration tests, not just repositories.