2

I have a problem with overriding beans in integration tests in Spring (with Spock).

Let's say this is my application config:

@EnableWebMvc
@SpringBootApplication
@Configuration
class Main {
    @Bean
    Race race(Car car) {
        // ...
    }

    @Bean
    Car car() {
        // ...
    }
}

And I have 2 separate integration tests that I want to have to separate Car implementations provided.

@Slf4j
@SpringApplicationConfiguration
class OneIntegrationSpec extends AbstractIntegrationSpec {

    @Configuration
    @Import(Main.class)
    static class Config {
        @Bean
        Car oneTestCar() {
            return new FerrariCar();
        }
    }
}


@Slf4j
@SpringApplicationConfiguration
class OtherIntegrationSpec extends AbstractIntegrationSpec {

    @Configuration
    @Import(Main.class)
    static class Config {
        @Bean
        Car otherTestCar() {
            return new TeslaCar();
        }
    }
}

When I run one of these I am getting: NoUniqueBeanDefinitionException cause Spring detects there are multiple car implementations. How to make test inner class Config with @Configuration annotation being loaded only for that particular test? I saw the approach with @Profile but that would mean creating separate profiles names for each IntegrationSpec which is a little bit violating a DRY. Is there another approach than @ActiveProfiles?

Dariusz Mydlarz
  • 2,940
  • 6
  • 31
  • 59
  • A quick and dirty solution could be to simply declare your test beans @Primary, which will circumvent the fact that there is more than one suitable bean, as the primary candidate will be used then. – Florian Schaetz Aug 16 '16 at 10:22
  • Yes, but then when I got `@Primary` in both `*IntegrationSpec` the same problem occurs – Dariusz Mydlarz Aug 16 '16 at 10:57
  • Why are you loading both `IntegrationSpec`s at the same time? You don't have the test itself (and how you are loading the Spring context) shown, but maybe don't use component scanning for those classes. – Jon Peterson Aug 16 '16 at 13:51
  • It's a spring boot application, and it automatically uses component scan on whole application – Dariusz Mydlarz Aug 16 '16 at 13:58

1 Answers1

0

I'm finding it hard to understand your use-case. Do you have to initialize entire applicationContext to test FerrariCar and TeslaCar? Can't you test them in isolation?

If integration test is the only way to go, you could try excludeFilters in @ComponentScan to disable auto-detecting your test config, as illustrated in https://stackoverflow.com/a/30199808/1553203 . You can then add specific test @Configuration for each Spec/Test by using @Import/@ComponentScan.

Community
  • 1
  • 1
phanin
  • 5,327
  • 5
  • 32
  • 50