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

如何使用Mockito为依赖注入的SpringBoot服务编写单元测试

问题背景

你已有两段核心业务代码:

  • UploadClass:封装S3客户端逻辑,负责将文件上传到S3存储桶,核心代码如下:
public class UploadClass{
    @Override
    public void upload(){
        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setContentLength(length);
        PutObjectResult putObjectResult =
                this.s3Client.putObject(container, object, data, metadata);
    }
}
  • MyClassServiceImpl:业务服务类,通过构造器注入UploadClass实例,在process()业务方法中调用上传能力,核心代码如下:
@Service
public class MyClassServiceImpl implements MyClassService{

    private final UploadClass uploadClass;

    @Autowired
    MyClassServiceImpl(final UploadClass uploadClass) {
        this.uploadClass = uploadClass;
    }

    @Override
    public void process() {
        // 其他业务逻辑
        this.uploadClass.upload();
    }
}

当前需求是为MyClassServiceImpl的process()方法编写单元测试,要求用Mockito模拟UploadClass实例,已搭好测试类基础结构:

@SpringBootTest
public class MyClassServiceTest{
    @Test
    void processTest() {

    }
}
具体实现方案

注意:UploadClass的upload()方法是无返回值的void类型,不需要设置模拟返回值,只需要屏蔽其真实S3上传逻辑、验证方法被正确调用即可。由于MyClassServiceImpl采用构造器注入,有两种常见测试实现方式,按需选择即可。


方式1:纯Mockito单元测试(推荐,执行效率高)

这种方式不需要启动完整Spring容器,测试运行速度快,适合纯业务逻辑验证:

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.verify;

// 启用Mockito注解支持
@ExtendWith(MockitoExtension.class)
public class MyClassServiceTest {

    // 生成UploadClass的模拟实例
    @Mock
    private UploadClass mockUploadClass;

    private MyClassService myClassService;

    @BeforeEach
    void setUp() {
        // 手动通过构造器注入mock对象,初始化被测服务
        myClassService = new MyClassServiceImpl(mockUploadClass);
    }

    @Test
    void processTest() {
        // 对void返回的upload方法打桩:调用时不执行真实上传逻辑
        doNothing().when(mockUploadClass).upload();

        // 执行被测业务方法
        myClassService.process();

        // 验证upload方法确实被调用,确认业务逻辑走到上传步骤
        verify(mockUploadClass).upload();

        // process方法内其他业务逻辑的断言、验证可补充在此处
    }
}

方式2:基于@SpringBootTest的集成测试写法

如果你需要加载Spring上下文做集成测试,用@MockBean替换容器内的真实UploadClass实例即可:

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;

import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.verify;

@SpringBootTest
public class MyClassServiceTest {

    // 将Spring容器中真实的UploadClass替换为mock实例,自动注入到依赖它的Bean中
    @MockBean
    private UploadClass mockUploadClass;

    @Autowired
    private MyClassService myClassService;

    @Test
    void processTest() {
        doNothing().when(mockUploadClass).upload();

        myClassService.process();

        verify(mockUploadClass).upload();
    }
}

补充说明

  • void方法不能使用when().thenReturn()语法打桩,除了示例里的doNothing(),如果要测试异常分支,还可以用doThrow()模拟上传抛出异常的场景:
    doThrow(new RuntimeException("S3连接失败")).when(mockUploadClass).upload();
    
  • 日常业务逻辑验证优先选第一种纯单元测试写法,不需要加载全量Spring配置,执行速度会快很多。

内容的提问来源于stack exchange,提问作者Nimasha Fernando

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 07:45:30