Junit结合Jmockit测试时如何按路径读取文件,解决文件上传测试报nio.fileNotFoundException问题
问题原因
- 路径拼接逻辑错误:
mockRequest.getContextPath()返回的是Web应用的上下文逻辑路径,并非本地文件系统的真实物理路径,直接拼接后指向的路径在本地不存在,触发文件找不到异常。另外你拼接后的路径是系统根目录下的/NPI_LAE/NPI-Maven/Files/db_value.txt,如果本地没有提前创建对应层级的目录并放入文件,也会触发异常。 - 类型转换错误:你创建的
MockMultipartFile实例和CommonsMultipartFile是MultipartFile接口下的两个不同实现类,直接强制转换必然抛出类转换异常,哪怕文件读取成功也无法通过该步骤。 - 异常处理无效:catch块中仅调用
e.getMessage(),没有打印错误堆栈也没有向上抛出异常,问题发生时无法获取具体错误信息,提升了排查难度。
可行解决方案
- 调整文件读取路径:单元测试的测试资源建议统一放到项目的
src/test/resources目录下,通过类加载器读取资源,避免硬编码物理路径的兼容性问题。如果没有引入Spring相关依赖,可以直接使用JDK自带的类加载器读取资源:
// JDK原生写法 URL resource = getClass().getClassLoader().getResource("db_value.txt"); Path path = Paths.get(resource.toURI()); byte[] data = Files.readAllBytes(path);
如果是Spring生态的项目,可以直接使用ClassPathResource简化读取:
// Spring生态写法 ClassPathResource resource = new ClassPathResource("db_value.txt"); byte[] data = Files.readAllBytes(resource.getFile().toPath());
- 删除错误的强转逻辑:
MockMultipartFile本身已经实现了MultipartFile接口,若UploadItemVO.setAdminTemplate的入参是MultipartFile类型,直接传入创建的MockMultipartFile实例即可,无需转换。如果业务代码确实要求入参是CommonsMultipartFile类型,请使用对应构造方法创建实例,不要强制转换。 - 完善异常处理逻辑:catch块中添加错误堆栈打印或日志输出,问题发生时可以快速定位根因。
修正后完整示例代码
MockMultipartHttpServletRequest mockRequest = new MockMultipartHttpServletRequest(); RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(mockRequest)); UploadItemVO uploadItemVO = new UploadItemVO(); mockRequest.setContextPath("/NPI_LAE"); mockRequest.setMethod("POST"); try { // 从测试资源目录读取文件,避免硬编码路径问题 URL resource = getClass().getClassLoader().getResource("db_value.txt"); Path path = Paths.get(resource.toURI()); byte[] data = Files.readAllBytes(path); MultipartFile file = new MockMultipartFile("db_value.txt", "db_value.txt", "text/plain", data); mockRequest.addFile(file); uploadItemVO.setMessages("Updating..."); // 直接传入MultipartFile类型参数,不需要强制转换 uploadItemVO.setAdminTemplate(file); } catch(Exception e) { e.printStackTrace(); throw new RuntimeException("单元测试初始化失败", e); }
内容的提问来源于stack exchange,提问作者Nagarjun Jeyachandran
相关产品推荐
相关产品推荐

