Spring Boot中@MockBean无法修改返回值问题排查
Spring Boot测试中@MockBean模拟未生效的问题排查与解决
问题根源
你的控制器代码直接通过new创建了TestServiceImpl实例,完全绕过了Spring的依赖注入容器:
public TestService testService = new TestServiceImpl(); // 直接实例化,不依赖Spring容器
@MockBean的作用是替换Spring容器中对应的Bean实例,但你的控制器根本没有从Spring容器获取TestService实例,而是用自己创建的对象,所以模拟操作完全不会影响到控制器的逻辑,自然返回原始的"Hello"。
解决方案
1. 修改控制器,使用Spring依赖注入
把控制器中直接new实例的代码改成依赖注入方式,推荐使用构造注入(Spring官方推荐,避免空指针问题,也更利于测试):
@RestController public class ExampleController { private final TestService testService; // 构造注入 public ExampleController(TestService testService) { this.testService = testService; } @GetMapping("/test") public String test() { return testService.greet(); } }
如果习惯用@Autowired,也可以这样写:
@RestController public class ExampleController { @Autowired private TestService testService; @GetMapping("/test") public String test() { return testService.greet(); } }
2. 调整测试类(可选,推荐Mock接口)
测试类中可以把@MockBean的类型改成接口TestService,更符合面向接口编程的思想,也更灵活:
@RunWith(SpringRunner.class) @WebMvcTest(ExampleController.class) // 建议指定具体控制器类,而非Application类 class ExampleApplicationTests { @Autowired MockMvc mockMvc; @MockBean private TestService testService; // Mock接口而非实现类 @Test void test() throws Exception{ doReturn("Hi").when(testService).greet(); mockMvc.perform(MockMvcRequestBuilders .get("/test") .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andExpect(jsonPath("$", notNullValue())) .andExpect(jsonPath("$", is("Hi"))); } }
验证效果
修改后,控制器会从Spring容器获取TestService实例,而@MockBean已经替换了容器中的实例,此时测试会调用模拟的greet方法返回"Hi",测试即可通过。
内容的提问来源于stack exchange,提问作者Matt
相关产品推荐
相关产品推荐

