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

如何用JUnit和Mockito测试Spring中向GridFS添加文件的方法?

public String addMaquette(MultipartFile maquette, String keySousRubrique, String projectId, String titrePage) throws IOException {

    DBObject metadata = new BasicDBObject();
    metadata.put("fileSize", maquette.getSize());
    metadata.put("keySousRubrique",keySousRubrique);
    metadata.put("projectId",projectId);
    metadata.put("titrePage",titrePage);

    Object fileID = template.store(maquette.getInputStream(), maquette.getOriginalFilename(), maquette.getContentType(), metadata);

    return fileID.toString();
} 

我是JUnit和Mockito单元测试的新手,不确定测试上述方法的最佳方式。能否为我提供该方法的单元测试指导或示例?

提前感谢!

单元测试指导与示例

这个方法的核心逻辑是构建元数据并调用模板存储文件,单元测试需聚焦三个核心验证点:

  1. 元数据是否按输入参数正确构建
  2. 文件存储方法是否被传入正确参数调用
  3. 异常场景是否能正确抛出

测试依赖说明

假设你的业务类名为MaquetteService,其中依赖的template是GridFsTemplate(MongoDB文件存储模板),测试时用Mockito模拟这些外部依赖,避免连接真实数据库。

完整测试代码示例

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
import com.mongodb.DBObject;
import com.mongodb.BasicDBObject;
import java.io.IOException;
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;

@ExtendWith(MockitoExtension.class)
class MaquetteServiceTest {

    // 注入被测试的业务类
    @InjectMocks
    private MaquetteService maquetteService;

    // 模拟依赖的文件存储模板
    @Mock
    private GridFsTemplate template;

    @Test
    void addMaquette_ShouldReturnFileId_WhenValidInput() throws IOException {
        // 1. 准备测试数据
        MockMultipartFile mockFile = new MockMultipartFile(
                "test.pdf",
                "test.pdf",
                "application/pdf",
                "dummy file content".getBytes()
        );
        String keySousRubrique = "section-001";
        String projectId = "proj-2024";
        String titrePage = "首页原型";
        String expectedFileId = "fs-10001";

        // 2. 模拟模板存储方法的返回值
        when(template.store(
                mockFile.getInputStream(),
                mockFile.getOriginalFilename(),
                mockFile.getContentType(),
                any(DBObject.class)
        )).thenReturn(expectedFileId);

        // 3. 调用被测试方法
        String actualFileId = maquetteService.addMaquette(mockFile, keySousRubrique, projectId, titrePage);

        // 4. 验证返回值正确性
        assertEquals(expectedFileId, actualFileId);

        // 5. 捕获并验证元数据是否正确构建
        ArgumentCaptor<DBObject> metadataCaptor = ArgumentCaptor.forClass(DBObject.class);
        verify(template).store(
                eq(mockFile.getInputStream()),
                eq(mockFile.getOriginalFilename()),
                eq(mockFile.getContentType()),
                metadataCaptor.capture()
        );
        DBObject capturedMetadata = metadataCaptor.getValue();
        assertEquals(mockFile.getSize(), capturedMetadata.get("fileSize"));
        assertEquals(keySousRubrique, capturedMetadata.get("keySousRubrique"));
        assertEquals(projectId, capturedMetadata.get("projectId"));
        assertEquals(titrePage, capturedMetadata.get("titrePage"));
    }

    @Test
    void addMaquette_ShouldThrowIOException_WhenStreamFails() throws IOException {
        // 1. 模拟文件流读取失败的场景
        MockMultipartFile mockFile = mock(MockMultipartFile.class);
        when(mockFile.getInputStream()).thenThrow(new IOException("文件流读取失败"));

        // 2. 验证方法是否正确抛出异常
        assertThrows(IOException.class, () ->
                maquetteService.addMaquette(mockFile, "test-key", "proj-001", "测试页面")
        );
    }
}

测试要点解释

  • Mock外部依赖:用@Mock注解模拟GridFsTemplate,避免测试依赖真实数据库环境
  • 参数捕获验证:通过ArgumentCaptor捕获传递给存储方法的元数据,逐一验证字段是否与输入匹配
  • 异常场景覆盖:模拟文件流读取失败的情况,验证方法是否正确向上抛出IOException
  • 返回值校验:确保方法返回的是存储模板返回ID的字符串形式

内容的提问来源于stack exchange,提问作者ismail fourati

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 20:22:49