Describe the bug
In larger Spring Boot's codebases it's not uncommon to have multiple beans of the same type where one of them is marked as @Primary.
Attempting to mock such bean with @SpringBean doesn't work as Spock Spring requires exactly one mocked bean's instance in the context (regardless of whether one of them is marked as primary).
This is an unnecessary limitation, especially that spring-boot-starter-test doesn't pose such limit when using @MockBean.
You can find a sample project presenting this issue with tests written using both SpringBean and MockBean here:
https://github.com/konradczajka/spock-spring-issue
The problem seems to be located in SpockMockPostprocessor which doesn't checks if one of located beans is marked as primary. I'd gladly provide a PR with a solution which seems to be working locally (which is highly inspired by the spring-boot-starter-test's code)
To Reproduce
With context configured as follows:
@Bean
Service2 service2NotPrimary() {
new Service2()
}
@Primary
@Bean
Service2 service2Primary() {
new Service2()
}
@Bean
IService1 service1(Service2 service2) {
return new Service1(service2)
}
and a test like this:
@SpringBean
Service2 service2 = Mock() {
generateQuickBrownFox() >> "blubb"
}
@Autowired
Service1 service1
def "injection with stubbing works"() {
expect:
service1.generateString() == "blubb"
}
Expected behavior
Passing test
Actual behavior
The test fails with a message similar to this:
Unable to register mock beanService2 expected a single matching bean to replace but found [service2Primary, service2NotPrimary]
Java version
18, but different versions don't affect the outcome
Buildtool version
18, but different versions don't affect the outcome
What operating system are you using
Linux
Dependencies
plugins {
id 'org.springframework.boot' version '2.7.2'
id 'io.spring.dependency-management' version '1.0.12.RELEASE'
id 'java'
id 'groovy'
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.spockframework:spock-core:2.1-groovy-3.0'
testImplementation 'org.spockframework:spock-spring:2.1-groovy-3.0'
}
Additional context
The same test written in Java/Mockito with spring-boot-starter-test and its @MockBean works as intended.
Describe the bug
In larger Spring Boot's codebases it's not uncommon to have multiple beans of the same type where one of them is marked as
@Primary.Attempting to mock such bean with
@SpringBeandoesn't work as Spock Spring requires exactly one mocked bean's instance in the context (regardless of whether one of them is marked as primary).This is an unnecessary limitation, especially that spring-boot-starter-test doesn't pose such limit when using
@MockBean.You can find a sample project presenting this issue with tests written using both
SpringBeanandMockBeanhere:https://github.com/konradczajka/spock-spring-issue
The problem seems to be located in
SpockMockPostprocessorwhich doesn't checks if one of located beans is marked as primary. I'd gladly provide a PR with a solution which seems to be working locally (which is highly inspired by the spring-boot-starter-test's code)To Reproduce
With context configured as follows:
and a test like this:
Expected behavior
Passing test
Actual behavior
The test fails with a message similar to this:
Java version
18, but different versions don't affect the outcome
Buildtool version
18, but different versions don't affect the outcome
What operating system are you using
Linux
Dependencies
Additional context
The same test written in Java/Mockito with
spring-boot-starter-testand its@MockBeanworks as intended.