Integration Testing With Spring – Organizing Configurations

Gil Zilberfeld explains how to organize Spring configurations for integration testing
In this series we're taking at Spring and its features supporting testing in general, and specifically integration testing.
Dependency injectionConfigurationsNested configurationsOrganizing configurations
Primary beansAvoiding problemsProfilesMocking I
Mocking IIMocking III

We’ve talked about nested configurations. Now, let’s move on to using imported configurations in a smart way.

Let’s say in the main app (as in “production”), I have a whole lot of beans I need to inject.

The thing not to do (although you might be tempted) is dump them all into one big configuration class. It might feel like “just one more bean wouldn’t hurt”. But it will. Maybe not today, maybe not tomorrow. But soon, and for the rest of your project life.

We might end up with tens, even hundreds of beans, so using a big class may be convenient in answering “where do I put my next shiny new bean”, but at the same time, we probably want to segment them better .

Separate Configurations

One way to do this is by service or functionality: Each service has its own configuration. With micro-services this is crucial. When we update the service, we update the configuration too, and deploy them as a single unit.

There are some things that are more cross-cutting, and less service related, like general database connectivity initialization beans. We can put those in a separate configuration class. Then for the application we can use @ContextConfiguration to load the right configuration classes:

As alternative, we can also  @Import at the configuration class level:

And then at the service class:

While both of these work, we conceal the fact that we’re using the DatabaseConfiguration in the service. This can come back to bite us later, as we’re carrying invisible baggage. So let’s stick with the first one.

And Testing Configurations?

When breaking down a full configuration into separate parts, we get a couple of advantages for testing:

  • We load only what we need for the test, not the entire system configuration
  • Run time (including load time) can seriously decrease
  • Less things that can fail our tests
  • Test setup becomes less of a hassle.

Here’s an alternative to the nested configuration example, only this time, the configuration is in a separate class.

In this case, the MainControllerConfiguration class is in the production part of the application, and the ControllerTestConfiguration is in the test part (obviously). The latter imports the former, which can save us time in creating objects we already have defined, and don’t need to change.

So when we use the ControllerTestConfiguration in a test it looks like this:

Notice that this way, we keep the link to the configuration through our ControllerTestConfiguration importer. Only it decides what to import or override. The test class is oblivious. This is quite cool.

So what’s “Overriding” a bean? That’s next.

Leave a Reply

Your email address will not be published. Required fields are marked *