Integration Testing with Spring – Mocking III

Gil Zilberfeld explains how to using mocking 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

In the last couple of posts we’ve discussed how we can use mocks in Spring integration tests. We’ve covered using a bean “prototype” and resetting mocks.

There is one more option.

The MockBean

By now you’re probably thinking: Those Spring guys must understand the need for proper mocking in integration tests. Didn’t they think about this stuff?

Well, of course they did. It’s called a MockBean.

A MockBean bean is injected by Spring, for testing purposes, for every integration test. And we get a nice shiny unscratched instance for each test. We don’t even need to handle auto-wiring, create a configuration and reset anything. Spring does all this magic for us.

This time, our integration test class looks like this:

Notice, we are not importing any configuration (or creating a bean). Instead of @Autowired instance we’ve got a @MockBean. That’s all it takes. Spring does the rest. Note that since there’s no configuration, all the set up should be done in the test class itself.

Everything you wanted to know about MockBeans but were afraid to ask

A @MockBean overrides by default a pre-configured bean. That means that if we import a Configuration with the same type of bean, the @MockBean is injected as a mock, overriding the factory method in Configuration class.

Also, remember that a @MockBean is a mock like any other Mockito mock, and therefore has defaults. If you want to change those (for example, change to a preferred deep-stubbing option, you can use it like this:

Finally, we know that a @MockBean resets after every test by default. If you want to change this option, you can use the reset before every test, or not at all.

Although that last one kinda misses the point.

On one hand, using a @MockBean gives good isolation from other test classes, since, as we’ve seen last time, it may be erased by an erroneous reset.

On the other hand, that may also be a limitation – if there are multiple setups we need on it, not just for our integration test class. Imagine we need to create mock object tree for multiple test classes to consume as a starting point, and each one customizes it for its purposes. In that case, the way to go is probably a prototype, and being very careful with resets.

That’s all about mocking for now. Next time: Data stuff.

Leave a Reply

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