spring-projects / spring-projects/spring-framework

@MockBean does not work with request-scoped Supplier<T> without explicit name

Open
#30,043 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

in: core type: bug
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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.