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
相关产品推荐
相关产品推荐

