如何正确编写处理MultipartFile的DocService单元测试?
如何正确编写处理MultipartFile的DocService单元测试?
看起来你在编写单元测试时遇到了几个典型问题,我来一步步帮你梳理和解决:
第一步:先修正DocService的代码问题
你的原代码里有几个逻辑和语法错误,这会导致运行时出错,先把这些问题解决:
@Data class Document { String name; byte[] byteFile; } @Service public class DocService { // 修正:原方法递归调用自己会导致栈溢出,改为调用私有构造方法 public Document makeDocument(MultipartFile file, String name) { return createDocument(file, name); } // 修正:私有方法需要接收file和name参数,否则无法访问外部变量;同时修复getbyte()的拼写错误(应为getBytes()) private Document createDocument(MultipartFile file, String name) { Document document = new Document(); document.setName(name); document.setByteFile(file.getBytes()); return document; } }
第二步:理解你遇到的测试错误原因
你碰到的when() requires an argument which has to be 'a method call on a mock'错误,核心问题是用错了Mockito的用法:
when()是用来给Mock对象打桩的方法,不能直接用在真实的DocService实例上。我们要测试DocService的真实业务逻辑,不需要Mock它本身,只需要构造合法的MockMultipartFile作为入参即可。
第三步:编写正确的单元测试
下面是基于JUnit 5的完整测试代码,直接实例化真实的DocService,传入模拟的MultipartFile后验证结果:
import org.junit.jupiter.api.Test; import org.springframework.mock.web.MockMultipartFile; import java.nio.charset.StandardCharsets; import static org.junit.jupiter.api.Assertions.*; class DocServiceTest { // 直接实例化真实的DocService,我们要测试它的真实逻辑 private final DocService docService = new DocService(); @Test void testMakeDocument() throws Exception { // 1. 构造测试用的MockMultipartFile String testDocName = "any"; String pdfContent = "<<pdf data>>"; MockMultipartFile mockFile = new MockMultipartFile( "file", "test contract.pdf", "application/pdf", pdfContent.getBytes(StandardCharsets.UTF_8) ); // 2. 调用要测试的方法 Document result = docService.makeDocument(mockFile, testDocName); // 3. 断言结果是否符合预期 assertNotNull(result, "返回的Document对象不能为null"); assertEquals(testDocName, result.getName(), "Document的name属性与预期不符"); assertArrayEquals(pdfContent.getBytes(StandardCharsets.UTF_8), result.getByteFile(), "Document的文件字节内容与预期不符"); } }
补充:如果DocService有其他依赖怎么办?
如果后续你的DocService引入了其他外部依赖(比如文件存储服务),那时候才需要用Mockito来Mock这些依赖,示例如下:
import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.mock.web.MockMultipartFile; import static org.mockito.Mockito.*; import static org.junit.jupiter.api.Assertions.*; @ExtendWith(MockitoExtension.class) class DocServiceTest { @Mock private FileStorageService storageService; // 假设这是DocService的外部依赖 @InjectMocks private DocService docService; // 把Mock的依赖注入到真实的DocService实例中 @Test void testMakeDocumentWithDependency() throws Exception { // 给Mock的依赖打桩,指定调用时的返回值 when(storageService.save(any(byte[].class))).thenReturn("file-saved-success"); // 构造测试用的MockMultipartFile MockMultipartFile mockFile = new MockMultipartFile("file", "test.pdf", "application/pdf", "test data".getBytes()); // 调用测试方法 Document result = docService.makeDocument(mockFile, "test-doc"); // 断言结果 assertNotNull(result); // 验证依赖方法是否被正确调用 verify(storageService, times(1)).save(any(byte[].class)); } }
备注:内容来源于stack exchange,提问作者Amit Kumar
相关产品推荐
相关产品推荐

