Integration Testing With Spring – Avoiding Problems

Gil Zilberfeld describes how to avoid problems created with bean injection in Spring integration tests
Standard
In this series we're taking at Spring and its features supporting testing in general, and specifically integration tests.
Dependency injectionConfigurationsNested configurationsOrganizing configurations
Primary beansAvoiding problemsProfilesMocking I - Lifecycle
Mocking II - ResetMocking III - MockBeanData I - @SQLData II - JDBC

Data III - JPA
Controllers IControllers IIConsumer tests

We already know that Spring is complex. And we’ve just scratched the surface. One of the problem with complex frameworks is that they do so much, that when something goes wrong they are not that smart about analyzing the situation. And that really gets in our way of doing actual programming.

For example, when a Bean doesn’t load, it can tell you that there was a problem loading it, but what exactly happened is hard to find on the stack. Especially if one dependency called another, and we are five levels deep in bean dependency. You can spend a lot of time here, so here are a couple of tips on how not to get there.

Don’t do anything important in the constructor

Beans usually create objects and return them. Those objects have constructors, that can do many things. But you shouldn’t.

You can store things in variables. But avoid any code in the constructor of your injected object. While we’re at it, definitely don’t have any static initializer that can create some “invisible” damage in the stack model of “who runs first”. If you need to initialize something in the object, add an Initialize method. I know it’s not Object Oriented in clean form, but we’re building components that integrate with a massive system, and it’s hard enough when it works.

Add a verification test in your test class

Remember the contextLoads() test that’s created for us in the Spring Boot test folder? What it does, as the name implies, is verify the ApplicationContext loads correctly. If it doesn’t, there’s not much point in running the rest of tests, right?

This test is like our canary in the coal mine. We can take this idea further.

When you add your own tests, especially when relying on automated wiring that Spring does from explicit configuration code, or god help us, implicitly and automatically. A simple test that checks that:

@Autowired JdbcTemplate jdbcTemplate;

@Test
public void verificationTest() {
      assertNotNull(jdbcTemplate);
}

We’ll get to JdbcTemplate in a future post, but suffice it to say it can be injected automatically to different objects in the system. Having this test in place localizes the error, and makes it easier to investigate what went wrong and fix it.

Whenever you’re starting a new test class, it’s advisable to have something like this around. And don’t throw it away, keep it around for stormy Spring weather. Winter is coming.

Leave a Reply

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