如何用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单元测试的新手,不确定测试上述方法的最佳方式。能否为我提供该方法的单元测试指导或示例?
提前感谢!
单元测试指导与示例
这个方法的核心逻辑是构建元数据并调用模板存储文件,单元测试需聚焦三个核心验证点:
- 元数据是否按输入参数正确构建
- 文件存储方法是否被传入正确参数调用
- 异常场景是否能正确抛出
测试依赖说明
假设你的业务类名为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
相关产品推荐
相关产品推荐

