如何用JUnit和Mockito测试Java中读取路径文件的方法(含日期参数示例)
用JUnit和Mockito测试文件路径读取方法
针对你提供的getFileAE方法,我们可以通过Mockito隔离真实文件系统的依赖,覆盖所有业务分支来完成单元测试。以下是具体实现步骤和测试用例:
依赖准备
确保你的测试依赖包含JUnit 5和Mockito(需要支持对象构造mock的版本,比如Mockito 3.5+):
<dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.9.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.9.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>4.11.0</version> <scope>test</scope> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-inline</artifactId> <version>4.11.0</version> <scope>test</scope> </dependency>
核心测试思路
原方法直接通过new File()创建文件对象,依赖真实文件系统。我们用Mockito的mockConstruction拦截File类的构造行为,模拟exists()方法的返回值或异常,从而在不操作真实文件的情况下测试业务逻辑。
测试用例
1. 文件存在时返回完整路径
验证当文件存在时,方法返回正确拼接的文件路径:
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.MockedConstruction; import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import java.io.File; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class FileReaderTest { // 替换为你的类名 private static final String TEST_DATE = "20240520"; private static final String EXPECTED_FILE_NAME = ConstantsFiles.FILE_NAME_AE + TEST_DATE + ConstantsFiles.FILE_EXTENSION; private static final String EXPECTED_FILE_PATH = ConstantsFiles.FILE_PATH_AE + EXPECTED_FILE_NAME; private FileReader target = new FileReader(); // 替换为你的类实例 @Test void getFileAE_FileExists_ReturnsFullPath() { try (MockedConstruction<File> mockedFile = Mockito.mockConstruction(File.class, (mock, context) -> { // 验证构造File时传入的路径是否正确 assertEquals(EXPECTED_FILE_PATH, context.arguments().get(0)); // 模拟文件存在 when(mock.exists()).thenReturn(true); })) { String result = target.getFileAE(TEST_DATE); assertEquals(EXPECTED_FILE_PATH, result); } } }
2. 文件不存在时返回空串
验证文件不存在时,方法返回空字符串:
@Test void getFileAE_FileDoesNotExist_ReturnsEmptyString() { try (MockedConstruction<File> mockedFile = Mockito.mockConstruction(File.class, (mock, context) -> { assertEquals(EXPECTED_FILE_PATH, context.arguments().get(0)); // 模拟文件不存在 when(mock.exists()).thenReturn(false); })) { String result = target.getFileAE(TEST_DATE); assertEquals("", result); } }
3. 发生异常时返回已拼接的路径
原方法捕获异常后返回已拼接的filePath,我们模拟调用exists()时抛出异常,验证返回值和日志输出:
import org.slf4j.Logger; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockedConstruction; import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; import java.io.File; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.*; @ExtendWith(MockitoExtension.class) class FileReaderTest { @Mock private Logger logger; // 若类中用@Slf4j,需通过反射或构造注入替换logger @InjectMocks private FileReader target; @Test void getFileAE_ThrowsException_ReturnsFilePath() { String testDate = "20240520"; String expectedFilePath = ConstantsFiles.FILE_PATH_AE + ConstantsFiles.FILE_NAME_AE + testDate + ConstantsFiles.FILE_EXTENSION; try (MockedConstruction<File> mockedFile = Mockito.mockConstruction(File.class, (mock, context) -> { assertEquals(expectedFilePath, context.arguments().get(0)); // 模拟权限异常 when(mock.exists()).thenThrow(new SecurityException("Permiso denegado")); })) { String result = target.getFileAE(testDate); assertEquals(expectedFilePath, result); // 验证错误日志是否输出 verify(logger).error("Error, el archivo no se pudo leer: Permiso denegado", any(SecurityException.class)); } } }
4. 日期参数的专项测试
针对日期参数,覆盖合法、非法输入场景,验证文件名拼接逻辑:
@Test void getFileAE_ValidDate_ConstructsCorrectPath() { String validDate = "20240601"; String expectedFilePath = ConstantsFiles.FILE_PATH_AE + ConstantsFiles.FILE_NAME_AE + validDate + ConstantsFiles.FILE_EXTENSION; try (MockedConstruction<File> mockedFile = Mockito.mockConstruction(File.class, (mock, context) -> { assertEquals(expectedFilePath, context.arguments().get(0)); when(mock.exists()).thenReturn(true); })) { String result = target.getFileAE(validDate); assertEquals(expectedFilePath, result); } } @Test void getFileAE_InvalidDate_ConstructsPathAsIs() { String invalidDate = "fecha-invalida-2024"; String expectedFilePath = ConstantsFiles.FILE_PATH_AE + ConstantsFiles.FILE_NAME_AE + invalidDate + ConstantsFiles.FILE_EXTENSION; try (MockedConstruction<File> mockedFile = Mockito.mockConstruction(File.class, (mock, context) -> { assertEquals(expectedFilePath, context.arguments().get(0)); when(mock.exists()).thenReturn(false); })) { String result = target.getFileAE(invalidDate); assertEquals("", result); } }
关键注意点
- 若你的类使用Lombok的
@Slf4j生成logger,需要通过反射或修改类的构造方法来注入mock logger,才能验证日志行为 - 所有测试用例均不依赖真实文件系统,保证测试的独立性和稳定性
- 覆盖了方法的所有分支:文件存在、文件不存在、异常场景,以及不同日期输入情况
内容的提问来源于stack exchange,提问作者Jonathan Ortiz
相关产品推荐
相关产品推荐

