@DataJpaTest in my Pocket

In my last post I’ve written about how to use the new Spring-Boot 1.4 test annotations in combination Spock for more boilerplate free test code. I’ve received some great feedback for this post (and it was even featured on some other blogs like the official Spring blog, Petri Kainulainen’s great Spring and testing blog, as well as Jacob Aae Mikkelsen’s Grails blog), for which I’m very grateful!) and I was also asked if I could provide an example of how to use @DataJpaTest in conjunction with multiple configured datasources. And so I thought great, that’ll be the topic of my next post.

Little Pocket Monster Shop of Horrors

Again I’ve tried to come up with some real world code examples, so let’s assume we have some kind of online shop in which you can buy small monsters in order to let them fight for you. Since cross-platform is all the rage nowadays, it might be a good idea for our shop to offer monsters from different vendors, which might be stored in distinct persistence layers.

We have the following package layout:
packages

The pokemon as well as the digimon package are both configured to use Spring-Data-Jpa with their own datasource. The PokemonConfig looks like this:

And the DigimonConfig looks really similar:

I must admit, this was the first time I’ve used Spring-Boot and Spring-Data-Jpa in conjunction with multiple datasources and the setup wasn’t all smooth sailing for me. The official docs are by no means bad, but the ride get’s pretty bumpy once you’ve got to manually disable different Spring-Boot autoconfigure features (since it is not always 100% percent intuitive on which condition autoconfiguration of a specific feature is disabled automagically – and Oliver Gierke seems to agree on this issue as well 😉) and some aspects mentioned inside the docs – like the usage of EntityManagerFactoryBuilder; I somehow could not inject the builder class without having a @Primary annotated datasource inside my Spring context – didn’t work for me at all. Oliver Gierke’s Spring-Data-Jpa example project on GitHub was a great help for me, since I could nearly copy-paste the EntityManager configuration code. Since I’m still kind of a Spring noob (I’ve started to use Spring in production with the advent of Spring-Boot, beforehand I was a zealous Grails crusader) it’s always a tad bit scary to leave the green meadows of Spring-Boot autoconfiguration and venture forth into the dark depths of vanilla Spring. But nevertheless, it’s almost consistently an enlightening and worthwhile experience once you’ve entangled the ominous stacktrace jungle.

@DataJpaTest

After getting the general application setup, the @DataJpaTest were so darn straight forward and simple, it even feels a bit awkward to devote a blog post to this topic.

You simply have to annotate your tests with @DataJpaTest (and @ContextConfiguration, since Spock is still lacking full support for new Spring-Boot 1.4 test annotations) and you’re good to go. Ah, it feels good to have the cozy Spring-Boot autoconfiguration magic back.

Here is an example test class:

I’m not entirely sure why this does work without further configuration, but while digging into the Spring-Boot source code I’ve found the following comment:

By default, tests annotated with @DataJpaTest will use an embedded in-memory database (replacing any explicit or usually auto-configured DataSource). The @AutoConfigureTestDatabase annotation can be used to override these settings.

So I think it might be safe to assume, these tests don’t need to care whether you are using multiple datasources, or a single autoconfigured one, they seem to be quite decoupled from this part of the application configuration and I think we will get further information about this annotation once Spring-Boot 1.4 is finally released.

I’ve uploaded the sample project on GitHub and I’m looking forward to any comments and/or questions about this topic.

  • It is possible to test the integration between your Inventory class and Pokedex/Digivice as well? I am trying to do something similar by using the snippet above as a starting point, but when I try to autowire the Inventory I get an UnsatisfiedDependencyException. I am very new to Spring, so I’m not sure how I should tackle the issue. Any idea? Thanks!