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

Spring Boot中使用Mockito如何Mock Service类内的本地方法

同Service类内部方法Mock实现方案

核心原理

你当前的测试代码使用@InjectMocks注入的是普通的MyServiceImpl实例,调用内部方法时会直接执行真实逻辑,无法单独Mock指定方法。我们可以使用Mockito的**Spy(间谍对象)**实现部分Mock:在真实对象的基础上,仅自定义Mock指定的内部方法,其余方法仍走真实逻辑,刚好适配你测试getSomething、仅Mock同类doSomething的需求。

方案一:纯Mockito单元测试(不启动Spring上下文)

这是单元测试优先推荐的方案,执行速度快,不需要依赖Spring环境。

实现步骤

  1. 将测试类中原来的@InjectMocks注解替换为@Spy,Spy会自动注入你声明的@Mock依赖
  2. 使用doReturn语法定义内部方法的Mock返回值(不要用when().thenReturn,会触发真实方法执行)

完整测试代码

// JUnit5 写法,JUnit4 替换为 @RunWith(MockitoJUnitRunner.class)
@ExtendWith(MockitoExtension.class)
public class MyServiceImplTest {

    @Mock
    SomeOtherService otherService;

    // 替换@InjectMocks为@Spy,生成部分Mock的实例
    @Spy
    MyServiceImpl myServiceImpl;

    @Test
    public void testGetSomething() {
        // 1. 构造测试数据
        Integer testId = 10;
        Integer mockSomethingId = 20;
        Something mockS = new Something();
        mockS.setId(mockSomethingId);
        List<Something> mockReturnList = new ArrayList<>();
        // 可按需给mockReturnList添加测试用的自定义元素

        // 2. Mock外部依赖的方法
        when(otherService.getOfSomething(testId)).thenReturn(mockS);
        // 3. Mock同类内部的doSomething方法,必须用doReturn避免触发真实调用
        doReturn(mockReturnList).when(myServiceImpl).doSomething(mockSomethingId);

        // 4. 执行待测试的getSomething方法
        List<Something> result = myServiceImpl.getSomething(testId);

        // 5. 断言结果+验证调用
        assertEquals(mockReturnList, result);
        verify(otherService, times(1)).getOfSomething(testId);
        verify(myServiceImpl, times(1)).doSomething(mockSomethingId);
    }
}

方案二:SpringBoot集成测试场景

如果你的测试需要启动Spring上下文,可以直接使用SpringBoot提供的@SpyBean注解,直接对容器中的Bean做Spy处理:

完整测试代码

@SpringBootTest
public class MyServiceImplSpringTest {

    @MockBean
    SomeOtherService otherService;

    // 直接注入Spy处理后的Service实例
    @SpyBean
    MyService myService;

    @Test
    public void testGetSomething() {
        // 测试逻辑和纯Mockito方案完全一致
        Integer testId = 10;
        Integer mockSomethingId = 20;
        Something mockS = new Something();
        mockS.setId(mockSomethingId);
        List<Something> mockReturnList = new ArrayList<>();

        when(otherService.getOfSomething(testId)).thenReturn(mockS);
        doReturn(mockReturnList).when(myService).doSomething(mockSomethingId);

        List<Something> result = myService.getSomething(testId);
        // 断言和验证逻辑同上
    }
}

常见注意事项

  • 禁止使用when(myServiceImpl.doSomething(anyInt())).thenReturn(xxx)的写法对Spy对象的方法做Mock,该写法会先真实执行一次doSomething方法,可能产生意外的逻辑执行或报错。
  • 不建议Mock私有内部方法,如果doSomething是私有方法,优先调整代码结构拆分逻辑,实在需要Mock私有方法可以引入PowerMock实现。
  • 如果MyServiceImpl是final类、或者doSomething是final方法,普通Mockito不支持Mock,同样需要引入PowerMock处理,或者调整代码去掉final修饰。

内容的提问来源于stack exchange,提问作者Arpith S

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 21:57:03