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

