spring-projects / spring-projects/spring-framework
@MockBean does not work with request-scoped Supplier<T> without explicit name
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 60.2k
- Forks
- 38.8k
- Avg merge
- 5d 2h
- Merged PRs (30d)
- 27
Description
Trying to define mock for request-scoped supplier does not work unless I explicitly name the mock.
The problem with hardcoding bean name is that name can be dependent on configuration (for example via use conditions).
If there is no RequestScope or I use custom interface there is no such problem.
Spring Boot 2.7.8 + JDK17
Simplified program:
package com.example.testspringoverridebeantest;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;
import org.springframework.web.context.annotation.RequestScope;
import java.util.function.Supplier;
@SpringBootApplication
public class TestSpringOverrideBeanTestApplication {
@Bean
@RequestScope
Supplier<String> word() {
return () -> "app";
}
@Bean
@RequestScope
@Profile("test") // just an example condition
@Primary
Supplier<String> testWord() {
return () -> "testapp";
}
public static void main(String[] args) {
SpringApplication.run(TestSpringOverrideBeanTestApplication.class, args);
}
}
@Service
record Greeter(Supplier<String> word) {
String hello() {
return "hello, " + word.get();
}
}
package com.example.testspringoverridebeantest;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import java.util.function.Supplier;
@SpringBootTest
class TestSpringOverrideBeanTestApplicationTests {
@Autowired
Greeter greeter;
@MockBean// (name = "testWord") // unbreaks but the name can vary!
Supplier<String> word;
@Test
void canOverrideBeanForTest() {
Mockito.when(word.get()).thenReturn("test");
Assertions.assertEquals("hello, test", greeter.hello());
}
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the supplied Spring Boot test using @MockBean Supplier, @RequestScope, and conditional beans, then compare it with the explicitly named mock case. Trace mock candidate resolution and verify that an unnamed request-scoped Supplier can be overridden when the bean name depends on configuration; add regression coverage for the behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, spring
- Domain
- backend, testing
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100