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

Spring Boot MockMvc测试:when()thenReturn()存根返回Null问题求助

问题分析与修复方案

我来帮你排查下为什么Mockito的Stub没生效返回null的问题,主要有两个核心原因,对应两种修复方式:

1. 最直接的原因:参数不匹配

你看控制器里调用服务层的时候,对source和target做了toUpperCase()转换:

SendingResponseDTO val = converterService.convertService(source.toUpperCase(), target.toUpperCase(), number);

但你的测试代码里,Stub用的是原字符串(哪怕是大写,万一测试用例里是小写就会匹配失败):

Mockito.when(cs.convertService(source, target, number)).thenReturn(dto);

Mockito的参数匹配是严格相等匹配,只要参数不完全一致,就会返回null。所以你只需要把Stub里的参数也转成大写,和控制器的调用保持一致就行:

Mockito.when(cs.convertService(source.toUpperCase(), target.toUpperCase(), number)).thenReturn(dto);

2. 更规范的测试姿势:修正测试注解的使用

你的测试类用了@SpringBootTest,这个注解会启动完整的Spring应用上下文,这时候你用@InjectMocks和@Mock注入的对象,很可能会被Spring自动装配的真实服务bean覆盖,导致Mock根本没生效。

对于Spring MVC控制器的单元测试,推荐用@WebMvcTest,它只会加载控制器相关的组件,配合@MockBean来模拟依赖的服务层,既轻量又准确。修改后的测试类如下:

@RunWith(SpringRunner.class)
@WebMvcTest(CurrencyConverterController.class)
public class CurrencyConverterControllerTest {
    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private CurrencyConverterService cs;

    @Test
    public void statusCheckTest() throws Exception {
        SendingResponseDTO dto = new SendingResponseDTO();
        String source = "GBP";
        String target = "USD";
        Double number = 32.56;
        
        dto.setSourceCurrency(source);
        dto.setTargetCurrency(target);
        dto.setNumber(number);
        dto.setTargetCurrencyValue(1.3136300664);
        dto.setTotalValue("$42.77");
        
        String apiURL = "/currency/converter/" + source + "/" + target + "/" + number;
        
        // 匹配控制器中实际调用的参数(转大写)
        Mockito.when(cs.convertService(source.toUpperCase(), target.toUpperCase(), number)).thenReturn(dto);
        
        mockMvc.perform(get(apiURL).contentType(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andDo(print())
                // 额外添加断言验证返回内容,让测试更严谨
                .andExpect(jsonPath("$.totalValue").value("$42.77"));
    }
}

这样修改后,Spring会自动把Mock的服务注入到控制器中,参数匹配也正确,就能得到预期的DTO了。

小建议

如果你的测试只需要验证控制器的逻辑,用@WebMvcTest足够了,不需要启动完整的应用上下文,测试速度会快很多。另外,添加对返回JSON内容的断言,可以确保接口返回的结果符合预期,而不仅仅是状态码正确。

内容的提问来源于stack exchange,提问作者Syam Kumar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:55:28