How to test Spring Data repositories?

tl;dr

To make it short – there’s no way to unit test Spring Data JPA repositories reasonably for a simple reason: it’s way to cumbersome to mock all the parts of the JPA API we invoke to bootstrap the repositories. Unit tests don’t make too much sense here anyway, as you’re usually not writing any implementation code yourself (see the below paragraph on custom implementations) so that integration testing is the most reasonable approach.

Details

We do quite a lot of upfront validation and setup to make sure you can only bootstrap an app that has no invalid derived queries etc.

  • We create and cache CriteriaQuery instances for derived queries to make sure the query methods do not contain any typos. This requires working with the Criteria API as well as the meta.model.
  • We verify manually defined queries by asking the EntityManager to create a Query instance for those (which effectively triggers query syntax validation).
  • We inspect the Metamodel for meta-data about the domain types handled to prepare is-new checks etc.

All stuff that you’d probably defer in a hand-written repository which might cause the application to break at runtime (due to invalid queries etc.).

If you think about it, there’s no code you write for your repositories, so there’s no need to write any unittests. There’s simply no need to as you can rely on our test base to catch basic bugs (if you still happen to run into one, feel free to raise a ticket). However, there’s definitely need for integration tests to test two aspects of your persistence layer as they are the aspects that related to your domain:

  • entity mappings
  • query semantics (syntax is verified on each bootstrap attempt anyway).

Integration tests

This is usually done by using an in-memory database and test cases that bootstrap a Spring ApplicationContext usually through the test context framework (as you already do), pre-populate the database (by inserting object instances through the EntityManager or repo, or via a plain SQL file) and then execute the query methods to verify the outcome of them.

Testing custom implementations

Custom implementation parts of the repository are written in a way that they don’t have to know about Spring Data JPA. They are plain Spring beans that get an EntityManager injected. You might of course wanna try to mock the interactions with it but to be honest, unit-testing the JPA has not been a too pleasant experience for us as well as it works with quite a lot of indirections (EntityManager -> CriteriaBuilder, CriteriaQuery etc.) so that you end up with mocks returning mocks and so on.

Leave a Comment