Integration Testing with Spring – Primary Beans

Gil Zilberfeld explains the Primary bean annotation for using in integration tests.

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

Last time we talked about breaking down configurations into small parts, so we can work in smaller chunks, that make our integration tests easier. This leads us to the next subject.

Remember that question we had? How does Spring know which bean to inject if it has multiple factory method for the same type? Let’s answer this in a single configuration class.

Let’s say in our main configuration class there are two beans of type Printer. We already talked about how to select a bean using its name. But Spring gives us a way to specify a default bean: @Primary.

When Spring sees a class with:

It will inject the DotMatrixPrinter one, because that bean has the @Primary annotation.

How can we use @Primary in integration tests?

@Primary becomes very effective in tests, because we might want to override the bean that is already defined in production. Let’s say our Printer type is configured in the app configuration like this:

So Printer will always result in injecting a LaserPrinter.  However, in our test we want to inject a mock Printer.

So lets create a test configuration:

Now, remember that when we import a configuration, there’s no “override” operation between the configurations, it’s adding the beans from the imported configuration to the importing one.

What happens when we use the PrinterTestConfiguration? The bean mockPrinter we added with @Primary tells Spring to load itself “over” the laserPrinter production one. The only trick is to not specify a @Primary in the main configuration.

Leave a Reply

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