You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot控制器JUnit测试when().thenReturn()失效如何解决?

问题原因
  • 你的FundController中FundUtil是直接new出来的实例,没有交给Spring容器管理,测试类中的msUtil和Controller实际使用的不是同一个对象,且你测试类里的msUtil是自己创建的普通对象,不是Mockito生成的Mock对象,调用when().thenReturn()时才会抛出MissingMethodInvocationException异常:Mockito只允许对Mock/Spy对象的方法进行打桩。
  • 你在测试类的setUp方法中手动覆盖了Spring注入的@MockBean FundDAO msDAO,自己new了一个DAO实例,导致你打桩的对象和Controller中注入的对象不是同一个,Mock逻辑自然不生效。
  • 测试方法中调用的请求路径和Controller定义的路径不一致,且缺少必填的@RequestBody请求体参数,就算Mock逻辑正常也会返回400/404错误。
  • 如果你用的是JUnit4,缺少@RunWith(SpringRunner.class)注解会导致@MockBean不生效。
修复步骤

1. 修正Controller的依赖注入逻辑

不要手动实例化依赖,全部交给Spring注入:

@RestController
public class FundController {  
  @Autowired
  private FundDAO msDAO;
  @Autowired // 把FundUtil也改成注入
  private FundUtil msUtil;

  // 其余业务代码保持不变
}

2. 修正测试类配置

移除手动实例化Mock对象的逻辑,把FundUtil也注册为MockBean,JUnit4环境添加@RunWith注解:

@RunWith(SpringRunner.class) // JUnit4必须加,JUnit5可省略
@WebMvcTest(controllers = FundController.class)
@ActiveProfiles("test")
public class FundTest {

    @Autowired
    private MockMvc mockMvc;
       
    @MockBean
    private FundDAO msDAO;

    @MockBean // 新增,让Spring把Controller中的FundUtil替换为Mock对象
    private FundUtil msUtil;

    private fundName fundName;
    
    @Before
    public void setUp() { 
        fundName = MockData.getfundName();
        // 删掉下面两行手动实例化的代码,不要覆盖Spring注入的Mock对象
        // msUtil = new FundsOrchestratorUtil();
        // msDAO = new FundsOrchestratorDAO();
    }

3. 修正测试方法逻辑

补全请求参数,修正请求路径,补充所有需要Mock的方法:

@Test
public void shouldFetchAllUsers() throws Exception {
    FundSearchResponse fundSearchResponse = MockData.getfundsSearchResponse();
    
    // 对Mock对象的方法打桩
    when(msUtil.validatefundSearchRequest(any(fundName.class), anyInt())).thenReturn(true);
    // 补充buildServiceResponse方法的打桩,避免返回null导致异常
    when(msUtil.buildServiceResponse(Constants.CODE_200_SUCCESS)).thenReturn(/* 构造你期望返回的ServiceResponse对象 */);
    when(msDAO.fundNameSearch(anyString(), anyInt())).thenReturn(fundSearchResponse);

    // 构造JSON请求体,补全请求参数
    ObjectMapper objectMapper = new ObjectMapper();
    String requestJson = objectMapper.writeValueAsString(fundName);
    
    this.mockMvc.perform(post("/v1/fund/search") // 修正路径,和Controller保持一致
                .contentType(MediaType.APPLICATION_JSON)
                .content(requestJson)
                .param("limit", "5"))
            .andExpect(status().isOk());
}

内容的提问来源于stack exchange,提问作者Masoom Raza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 19:54:03