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

使用JUnit测试Java中MultipartFile接口时出现空指针异常求助

控制器单元测试空指针异常排查与修复

问题场景

我要为一个在Postman中可正常运行的接口编写单元测试,接口代码如下:

@PostMapping("/uploadGText")
public ResponseEntity<Object> translateGt(@RequestParam("text") MultipartFile file, 
                        @RequestParam("langI") String langI,
                        @RequestParam("langO") String langO) throws IOException{
  
    String fileName = fileStorageService.storeFile(file);
    String path = "Uploads\\"+fileName;
  
    TxtFile tFile = new TxtFile();
    tFile.getPath(path,langI,langO);
                        
    return downloadFile(tFile.getNewPath());
}

当前的单元测试代码如下,想要实现参数传递并完成断言:

@Test
public void shouldExecuteTranslateController() throws IOException {

    Path path = Paths.get("Uploads\\testText.txt");
    String name = "text";
    String originalFileName = "testText.txt";
    String contentType = "text/plain";
    byte[] content = null;
    try {
        content = Files.readAllBytes(path);
    } catch (final IOException e) {
    }
    MultipartFile result = new MockMultipartFile(name,
            originalFileName, contentType, content);
    TranslateController tr = new TranslateController();
    tr.translateGt(result,"en","es");
    //assertEquals("textTet", tr.translateGt(result,"en","es");)
}

执行测试时抛出空指针异常,异常栈如下:

java.lang.NullPointerException
    at com.jalasoft.convert.controller.endpoint.TranslateController.translateGt(TranslateController.java:32)
    at com.jalasoft.convert.controller.endpoint.TranslateControllerTest.shouldExecuteTranslateController(TranslateControllerTest.java:34)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)

问题根源

空指针出在控制器第32行的fileStorageService.storeFile(file)代码——你直接new TranslateController()创建实例时,控制器依赖的fileStorageService成员变量没有被注入,处于null状态,和MultipartFile本身无关。

修复方案

方案1:用Spring Test框架注入控制器(推荐)

借助Spring的测试框架,让容器帮你注入依赖,同时用MockMvc模拟真实HTTP请求,更贴合接口实际运行场景:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import java.nio.file.Files;
import java.nio.file.Paths;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@RunWith(SpringRunner.class)
@WebMvcTest(TranslateController.class)
public class TranslateControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void shouldExecuteTranslateController() throws Exception {
        MockMultipartFile testFile = new MockMultipartFile(
                "text",
                "testText.txt",
                "text/plain",
                Files.readAllBytes(Paths.get("Uploads\\testText.txt"))
        );

        mockMvc.perform(multipart("/uploadGText")
                        .file(testFile)
                        .param("langI", "en")
                        .param("langO", "es"))
                .andExpect(status().isOk());
        
        // 可扩展断言:验证返回文件的内容、响应头(如Content-Disposition)等
    }
}

方案2:手动Mock依赖

如果不想启动Spring容器,用Mockito手动mockfileStorageService并注入控制器:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.http.ResponseEntity;
import java.nio.file.Files;
import java.nio.file.Paths;
import static org.mockito.Mockito.when;
import static org.junit.Assert.assertEquals;

@RunWith(MockitoJUnitRunner.class)
public class TranslateControllerTest {

    @Mock
    private FileStorageService fileStorageService; // 替换为你的实际服务类名

    @Test
    public void shouldExecuteTranslateController() throws Exception {
        MockMultipartFile testFile = new MockMultipartFile(
                "text",
                "testText.txt",
                "text/plain",
                Files.readAllBytes(Paths.get("Uploads\\testText.txt"))
        );

        // Mock文件存储方法的返回值
        when(fileStorageService.storeFile(testFile)).thenReturn("testText.txt");

        TranslateController controller = new TranslateController();
        // 手动注入Mock服务(需给控制器添加setter方法,或用反射注入)
        controller.setFileStorageService(fileStorageService);

        ResponseEntity<Object> response = controller.translateGt(testFile, "en", "es");
        // 断言响应状态码
        assertEquals(200, response.getStatusCodeValue());
    }
}

额外注意事项

  • 不要忽略IO异常:测试代码里的空try-catch会导致文件读取失败时content为null,应该让测试直接失败,避免后续执行无效代码
  • 完善断言逻辑:根据downloadFile的返回值,添加对文件内容、响应头的断言,提升测试的有效性

内容的提问来源于stack exchange,提问作者Gabriel Valda Arraya

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 18:05:25