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

如何正确编写处理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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 13:30:27