Last time we talked about breaking down configurations into small parts, so we can work in smaller chunks, that make our integration testing 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.

@Configuration
public class PrinterMainConfiguration {

  @Bean
  public Printer laserPrinter() {
    return new LaserPrinter();
  }

  @Bean
  @Primary
  public Printer dotMatrixPrinter() {
    return new DotMatrixPrinter();
  }
}Code language: PHP (php)

When Spring sees a class with:

@Autowired Printer printer;Code language: CSS (css)

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:

@Configuration
public class PrinterMainConfiguration {

  @Bean
  public Printer laserPrinter() {
    return new LaserPrinter();
  }
}Code language: PHP (php)

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:

@Configuration
@Import(PrinterMainConfiguration.class)
public class PrinterTestConfiguration {

  @Bean
  @Primary
  public Printer mockPrinter() {
    return Mockito.mock(Printer.class);
  }
}Code language: CSS (css)

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.

Check out the following workshops where I talk about testing in Spring:

Categories: Uncategorized

0 Comments

Leave a Reply

Avatar placeholder

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