在Java后端开发中,XML上传功能常常涉及文件解析、数据校验、持久化等多个环节,Service层作为业务逻辑的核心载体,单元测试时需要避免依赖真实的文件存储、数据库等资源,此时使用Mockito模拟相关依赖是高效的解决方案。

环境准备
首先需要在项目中引入Mockito和JUnit的相关依赖,如果是Maven项目,可在pom.xml中添加如下配置:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.5.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
待测试的Service层示例
假设我们有一个XML上传的Service类,依赖文件存储服务和XML解析服务,代码如下:
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
public class XmlUploadService {
private final FileStorageService fileStorageService;
private final XmlParseService xmlParseService;
public XmlUploadService(FileStorageService fileStorageService, XmlParseService xmlParseService) {
this.fileStorageService = fileStorageService;
this.xmlParseService = xmlParseService;
}
/**
* 处理XML文件上传逻辑
* @param file 上传的XML文件
* @return 上传结果信息
* @throws IOException 文件处理异常
*/
public String handleXmlUpload(MultipartFile file) throws IOException {
// 校验文件类型
if (!"xml".equalsIgnoreCase(file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf(".") + 1))) {
throw new IllegalArgumentException("仅支持XML格式文件上传");
}
// 存储文件
String filePath = fileStorageService.storeFile(file);
// 解析XML内容
String parseResult = xmlParseService.parseXml(filePath);
return "文件上传成功,路径:" + filePath + ",解析结果:" + parseResult;
}
}
其中FileStorageService和XmlParseService是Service层的依赖,我们会在测试中模拟这两个对象。
使用Mockito模拟Service层依赖
创建测试类并初始化Mock对象
我们创建对应的测试类,使用Mockito的注解或者手动创建Mock对象:
import org.junit.jupiter.api.BeforeEach;
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.web.multipart.MultipartFile;
import java.io.IOException;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import static org.junit.jupiter.api.Assertions.*;
@ExtendWith(MockitoExtension.class)
class XmlUploadServiceTest {
@Mock
private FileStorageService fileStorageService;
@Mock
private XmlParseService xmlParseService;
@InjectMocks
private XmlUploadService xmlUploadService;
private MultipartFile mockXmlFile;
@BeforeEach
void setUp() {
// 创建模拟的MultipartFile对象
mockXmlFile = new MultipartFile() {
@Override
public String getName() {
return "xmlFile";
}
@Override
public String getOriginalFilename() {
return "test.xml";
}
@Override
public String getContentType() {
return "application/xml";
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public long getSize() {
return 1024;
}
@Override
public byte[] getBytes() throws IOException {
return "<root><data>test</data></root>".getBytes();
}
@Override
public java.io.InputStream getInputStream() throws IOException {
return new java.io.ByteArrayInputStream(getBytes());
}
@Override
public void transferTo(java.io.File dest) throws IOException, IllegalStateException {
// 模拟实现,无需实际操作
}
};
}
}
编写正常上传场景的测试用例
模拟依赖方法的返回值,验证Service层的正常逻辑:
@Test
void testHandleXmlUpload_Success() throws IOException {
// 模拟依赖方法的返回值
when(fileStorageService.storeFile(any(MultipartFile.class))).thenReturn("/upload/test.xml");
when(xmlParseService.parseXml("/upload/test.xml")).thenReturn("数据解析完成");
// 执行待测试方法
String result = xmlUploadService.handleXmlUpload(mockXmlFile);
// 验证结果
assertTrue(result.contains("文件上传成功"));
assertTrue(result.contains("数据解析完成"));
}
编写异常场景的测试用例
测试非XML文件上传的场景,验证异常抛出是否符合预期:
@Test
void testHandleXmlUpload_InvalidFileType() {
// 创建一个非XML格式的模拟文件
MultipartFile invalidFile = new MultipartFile() {
@Override
public String getName() {
return "txtFile";
}
@Override
public String getOriginalFilename() {
return "test.txt";
}
@Override
public String getContentType() {
return "text/plain";
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public long getSize() {
return 512;
}
@Override
public byte[] getBytes() throws IOException {
return "test content".getBytes();
}
@Override
public java.io.InputStream getInputStream() throws IOException {
return new java.io.ByteArrayInputStream(getBytes());
}
@Override
public void transferTo(java.io.File dest) throws IOException, IllegalStateException {
}
};
// 验证异常抛出
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> {
xmlUploadService.handleXmlUpload(invalidFile);
});
assertEquals("仅支持XML格式文件上传", exception.getMessage());
}
验证依赖方法的调用情况
我们可以使用Mockito的verify方法验证依赖方法是否被正确调用:
@Test
void testHandleXmlUpload_VerifyDependencyCall() throws IOException {
when(fileStorageService.storeFile(any(MultipartFile.class))).thenReturn("/upload/test.xml");
when(xmlParseService.parseXml("/upload/test.xml")).thenReturn("解析结果");
xmlUploadService.handleXmlUpload(mockXmlFile);
// 验证fileStorageService的storeFile方法被调用了一次
org.mockito.Mockito.verify(fileStorageService, org.mockito.Mockito.times(1)).storeFile(mockXmlFile);
// 验证xmlParseService的parseXml方法被调用了一次,且参数为存储的文件路径
org.mockito.Mockito.verify(xmlParseService, org.mockito.Mockito.times(1)).parseXml("/upload/test.xml");
}
注意事项
- 模拟对象时需要注意方法参数的匹配,如果需要匹配具体参数可以使用
eq方法,匹配任意参数使用any方法。 - 如果依赖方法会抛出检查异常,需要在模拟时声明抛出异常,或者在测试中处理对应异常。
- 对于void类型的依赖方法,可以使用
doThrow或者doNothing来模拟行为。
通过上述步骤,我们可以完整使用Mockito模拟XML上传的Service层,覆盖正常和异常场景的测试,保障Service层逻辑的正确性。
MockitoXML上传Service层测试单元测试Java修改时间:2026-06-28 21:39:39