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

JUnit方法模拟传对象:post调用返回空值求解决方案

解决Mockito模拟多次不同对象参数的HTTP调用返回值问题

你说的完全正确——问题核心就是对象引用不匹配:目标方法里每次调用httpService.post()时都新建了ServiceCallDto实例,而你测试代码里用eq()匹配的是自己创建的另一个实例,Mockito的eq()默认是基于对象引用(或者equals方法,如果类重写了的话)来匹配的,所以自然匹配失败,返回了Mockito的默认空值。

下面给你几个可行的替代方案,按需选择:

方案1:使用refEq()进行反射匹配(推荐,简单直接)

Mockito提供了refEq()方法,它会通过反射对比对象的字段值,而不是依赖对象引用或者equals方法。这样只要两次的ServiceCallDto字段值和目标方法里的一致,就能匹配成功。

示例代码:

@Test
public void testMyMethod() {
    // 准备第一次调用的预期Dto字段
    ServiceCallDto expectedFirstDto = new ServiceCallDto();
    expectedFirstDto.setXXX("firstValue"); // 对应目标方法里第一次设置的属性
    
    // 准备第二次调用的预期Dto字段
    ServiceCallDto expectedSecondDto = new ServiceCallDto();
    expectedSecondDto.setXXX("secondValue"); // 对应目标方法里第二次设置的属性
    
    // 模拟第一次调用
    when(httpService.post(anyString(), any(HttpHeaders.class), refEq(expectedFirstDto)))
        .thenReturn("First Response");
    
    // 模拟第二次调用
    when(httpService.post(anyString(), any(HttpHeaders.class), refEq(expectedSecondDto)))
        .thenReturn("Second Response");
    
    // 执行目标方法
    myTargetObject.myMethod();
    
    // 验证调用次数和参数(可选)
    verify(httpService, times(2)).post(anyString(), any(HttpHeaders.class), any(ServiceCallDto.class));
}

方案2:自定义参数匹配器(argThat())

如果需要更灵活的校验逻辑(比如只校验部分字段),可以用argThat()结合Lambda表达式自定义匹配规则:

@Test
public void testMyMethod() {
    // 模拟第一次调用:校验Dto的特定字段
    when(httpService.post(anyString(), any(HttpHeaders.class), 
        argThat(dto -> "firstValue".equals(dto.getXXX()))))
        .thenReturn("First Response");
    
    // 模拟第二次调用:校验另一组字段
    when(httpService.post(anyString(), any(HttpHeaders.class), 
        argThat(dto -> "secondValue".equals(dto.getXXX()))))
        .thenReturn("Second Response");
    
    // 执行目标方法
    myTargetObject.myMethod();
}

方案3:如果不需要校验Dto参数,直接用any()

如果你的测试只关心httpService.post()被调用了两次,不关心具体的Dto内容,可以直接用any(ServiceCallDto.class)匹配:

@Test
public void testMyMethod() {
    // 连续模拟两次调用的返回值
    when(httpService.post(anyString(), any(HttpHeaders.class), any(ServiceCallDto.class)))
        .thenReturn("First Response", "Second Response");
    
    // 执行目标方法
    myTargetObject.myMethod();
    
    // 验证调用次数
    verify(httpService, times(2)).post(anyString(), any(HttpHeaders.class), any(ServiceCallDto.class));
}

额外提示:重写ServiceCallDto的equals()方法

如果你的项目允许,也可以给ServiceCallDto重写equals()和hashCode()方法,让它基于字段值进行比较。这样原来的eq()匹配就能正常工作了——不过这种方式需要修改业务代码,适合Dto本身就应该有值相等逻辑的场景。


内容的提问来源于stack exchange,提问作者Milinda Kasun

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 10:32:43