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

如何用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 11:37:06