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

Mockito模拟SpringBoot同类内部方法调用?JUnit测试求助

问题分析与解决方案

你的测试代码存在几个关键问题,导致Mockito模拟未生效,下面逐一说明并给出修正方案:

1. Spy对象的模拟写法错误

对于@Spy注解的对象,使用when(spyObj.method()).thenReturn(...)会先执行真实的方法逻辑,这不仅会导致模拟失效,还可能触发原方法中的RestTemplate调用抛出错误。正确的写法应该使用doReturn(...).when(spyObj).method(...),跳过真实方法的执行。

2. RestTemplate模拟的参数不匹配

你的实际代码中,restTemplate.exchange的第四个参数是ThirdResponse.class,但测试里写的是eq(String.class),参数类型不匹配,导致模拟无法触发。

3. 返回值使用匹配器而非实例

thenReturn(any(ResponseEntity.class))是错误的,any()是参数匹配器,不能用作返回值,需要返回具体的ResponseEntity实例或Mock对象。

4. 依赖注入的注解问题

需要确保RestTemplate被正确Mock并注入到MyService中,修正注解的写法和类名大小写(你的测试里写的Myservice是小写,实际类名是MyService)。


修正后的测试代码

import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class) // JUnit 5需要的扩展
public class MyServiceTest {

    @Mock
    private RestTemplate restTemplate;

    @InjectMocks
    @Spy
    private MyService myService; // 修正类名大小写

    @ParameterizedTest
    @DisplayName("Should check the flow")
    @MethodSource("com.web.test.utilities.TestUtils#getRequest")
    public void flowTest(Request request){
        // 1. 模拟RestTemplate的exchange方法,参数匹配实际调用
        ThirdResponse mockThirdResponse = mock(ThirdResponse.class);
        ResponseEntity<ThirdResponse> mockResponse = ResponseEntity.ok(mockThirdResponse);
        when(restTemplate.exchange(
                anyString(),
                eq(HttpMethod.POST),
                any(HttpEntity.class),
                eq(ThirdResponse.class) // 和实际代码的参数类型一致
        )).thenReturn(mockResponse);

        // 2. 模拟MyService的thirdMethod,使用doReturn避免执行真实方法
        doReturn(mockResponse).when(myService).thirdMethod(any(ThirdRequestObj.class));

        // 执行测试方法
        myService.flow(request);

        // 这里可以添加断言,比如验证thirdMethod被调用的次数
        // verify(myService, times(2)).thirdMethod(any(ThirdRequestObj.class));
    }
}

额外说明

  • 如果你的目标只是验证flow方法的逻辑,而不想关心thirdMethod的具体实现,直接模拟thirdMethod是合理的;如果需要测试thirdMethod和私有方法的联动,建议考虑:
    • 调整代码结构,将私有方法的逻辑提取为公共方法或单独的类,方便测试(这是更推荐的做法,因为私有方法属于实现细节,测试应聚焦于公共接口)
    • 若必须测试私有方法,可以使用PowerMock,但一般不推荐,会增加测试复杂度。

内容的提问来源于stack exchange,提问作者B Chitra

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 12:55:53