To illustrate the issue I have two separate @SpringBootTest classes each of which have an inner @TestConfiguration static class both of which create the same bean.
When I run TestB I see that the "stringBeans" bean from TestA is being created and used and vice versa. Why is this? I want to be able to create different tests that define the same bean but with that bean configured differently. How can I achieve this?
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = "spring.main.allow-bean-definition-overriding=true")
public class TestA {
@TestConfiguration
static class TestConfig {
@Bean
@Primary
public String stringBeans() {
System.out.println("Creating string bean from Test A");
return "Test A";
}
}
@Test
public void testA() {
System.out.println("Running Test A");
}
}
When running the above test I see the following output:
Creating string bean from Test B
Running Test A
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = "spring.main.allow-bean-definition-overriding=true")
public class TestB {
@Autowired
String stringBeans;
@TestConfiguration
static class TestConfig {
@Bean
@Primary
public String stringBeans() {
System.out.println("Creating string bean from Test B");
return "Test B";
}
}
@Test
public void testB() {
System.out.println("Running Test B");
assertThat(stringBeans).isEqualTo("Test B");
}
}
When running the above test the assert fails and I see the following output:
Creating string bean from Test A
Running Test B
I have tried creating separate classes annotated with @TestConfiguration and using @Import to pull them into each respective test but that does not resolve this issue consistently.
I was testing a Spring Cloud Function and it turned out I had a component scan defined in the application.yml in the test/resources folder that was causing both inner @TestConfiguration classes to be evaluated. So you need to be super careful with your test setup otherwise weird behaviour that can be difficult to trace can happen.
In this example I had my classes all defined under com.example.demo and an application.yml as follows
spring:
cloud:
function:
scan:
packages: com.example.demo
The tests run as expected after removing this unnecessary scan.