question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Override bean in Spring Boot 2.1 slice test with nested TestConfiguration

See original GitHub issue

I just migrated an application from Spring Boot 1.x to 2.1. One of my test is failing due to a change to bean overriding default.

I tried to set spring.main.allow-bean-definition-overriding to true but it’s not working. I managed to make it work by using a standalone @TestConfiguration class that I import. But if it’s nested, it does not work.

You can reproduce the issue with the following classes:

@Configuration
public class ClockConfig {
    @Bean
    public Clock clock() {
        return Clock.systemUTC();
    }
}
@Service
public class MyService {
    private final Clock clock;
    public MyService(Clock clock) {
        this.clock = clock;
    }
    public Instant now() {
        return clock.instant();
    }
}
@RestController
public class MyResource {
    private final MyService myService;
    public MyResource(MyService myService) {
        this.myService = myService;
    }
    @GetMapping
    public ResponseEntity<Instant> now() {
        return ResponseEntity.ok(myService.now());
    }
}

The failing test. The clock() method is never called with Spring Boot 2.1 whereas it was with Spring Boot 1.5 or Spring Boot 2.0.

@RunWith(SpringRunner.class)
@WebMvcTest(MyResource.class)
@ContextConfiguration(classes = MyService.class)
public class ResourceTest {
    @Autowired
    private MockMvc mvc;
    @Test
    public void test() {
    }
    @TestConfiguration
    static class TestConfig {
        @Bean
        public Clock clock() {
            return Clock.fixed(Instant.MIN, ZoneId.of("Z"));
        }
    }
}

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:1
  • Comments:7 (3 by maintainers)

github_iconTop GitHub Comments

3reactions
sgfltcommented, Jul 22, 2020

I have run into this issue too after splitting big app into modules as suggested in Structuring and Testing Modules and Layers with Spring Boot

In previous monolith there some test cases had nested static class annotated by @TestConfiguration, that provided Bean EmbeddedDatasource with database manually crafted from sql scripts. After splitting app into modules there are two types of errors. Spring boot version is unchanged: v2.2.6.RELEASE.

  1. org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name ‘setUp’ defined in class path resource. This error is caused by @ComponentScan in module that scans multiple nested static classes each containing definition of specific datasource.

If I rearrange code to avoid ComponentScan. The second problem arrises.

  1. org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type. Which complains about missing dependency in production code which is obviously not found because in module there is no ComponentScan nor SpringBootApplication.

Is there any possible solution to this situation? Respectively to preserve behavior of nested static classes in test case and test code still be able to access to production code.

Code example to better understanding:

@ExtendWith(SpringExtension.class)
@SpringBootTest
@AutoConfigureMockMvc
class TestCase {
  ...
  @TestConfiguration
  static class EmbeddedDatabaseConfiguration {
    @Bean
    @Primary
    DataSource setUp() {
     // datasource with custom data
      ...
    }
}


@ExtendWith(SpringExtension.class)
@SpringBootTest
@AutoConfigureMockMvc
class AnotherTestCase {
  ...
  @TestConfiguration
  static class EmbeddedDatabaseConfiguration {
    @Bean
    @Primary
   // this is in conflict with TestCase.EmbeddedDatabaseConfiguration after modularisation
    DataSource setUp() {
     // datasource with custom data
      ...
    }
}

Maybe it is for another issue, because my TestConfiguration is found and called, but the bean created is global and each test therefore can not mock it’s own implementation. TestConfigurations in single module app are behaving as expected.

0reactions
mbhavecommented, Jun 24, 2021

I ran the original sample and the tests which use @Import instead of @ContextConfiguration pass. I am going to close this issue because as @snicoll suggested using @ContextConfiguration in slice tests is quite unusual.

@sgflt The issue you’ve described might be slightly different because it does not involve @ContextConfiguration. If you think you’ve found a bug, please open another issue with a minimal sample that we can run to reproduce it.

Read more comments on GitHub >

github_iconTop Results From Across the Web

java - Override bean in Spring Boot 2.1 slice test with nested ...
Try to modify ContextConfiguration annotation. It should be: @ContextConfiguration(classes = {MyService.class,ClockConfig.class}) .
Read more >
[Solved]-Override bean in Spring Boot 2.1 slice test with ...
Coding example for the question Override bean in Spring Boot 2.1 slice test with nested TestConfiguration-Springboot.
Read more >
46. Testing - Spring
Spring Boot provides a number of utilities and annotations to help when testing your application. Test support is provided by two modules: spring-boot-test...
Read more >
Testing with Spring Boot's @TestConfiguration Annotation
It allows us to define additional beans or override existing beans in the Spring application context to add specialized configurations for ...
Read more >
Unit and Integration Testing in Spring Boot 2 - HowToDoInJava
Some of these beans may be overridden to mock certain behaviors. 2. Dependencies. 2.1. Junit 4 Tests (Default). To write tests in spring...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found