如何在Java中使用Junit和Mockito测试一个方法,该方法在这样的路径中创建一个文件[重复]

nbewdwxp  于 2023-04-28  发布在  Java
关注(0)|答案(2)|浏览(138)

此问题已在此处有答案

how to do a Unit Test with Junit and mockito in java on methods that read a path and file(1个答案)
8小时前关闭
我想在Java中使用JUnit和Mockito测试一个方法,这个方法基本上是读取一个路径并创建一个文件,如果文件存在,请删除它并重新创建它,有什么例子可以帮助我吗?
下面是我想测试的方法:

public String getFilePE(String fecha) {
    String fileName = null;
    String filePath = null;
    File file = null;

    try {
        logger.info("Generando archivo para PE");
        fileName = ConstantsFiles.FILE_NAME_PE + fecha + ConstantsFiles.FILE_EXTENSION;
        filePath = ConstantsFiles.FILE_PATH_PE + fileName;
        logger.info(filePath);
        
        file = new File(filePath);
        if (file.createNewFile()) {
            logger.info("Archivo creado con exito " + file.getName());
        } else {
            Files.deleteIfExists(Paths.get(filePath));
        }
    } catch (IOException ex) {
        logger.error("Error, el archivo no se pudo generar: " + ex.getMessage(), ex);
    }
    return filePath;
}
sxissh06

sxissh061#

检查file.createNewFile()是否调用

@Test
 public void testGetFilePE() {
 File file = mock(File.class)
 yourMockedService.getFilePE("String"); 
 verify(file).createNewFile();
}

如果你需要测试所有的情况。类似于else语句或catch块。您需要模拟抛出错误并模拟if语句

hlswsv35

hlswsv352#

这里的问题是您在测试中使用了文件系统。这将添加单元测试中不应具有的外部依赖项。文件系统可能处于正确的状态,也可能不处于正确的状态,它们有缓存,可能会随机地使您的测试跳闸,并且它们通常比只使用内存慢得多。最好的办法是重构代码(或者实际上是测试代码的调用者),使其与InputStreamOutputStream一起工作,在真实的生活中,您可以轻松地与FileInputStreamFileOutputStream一起使用,但分别与ByteArrayInputStreamByteArrayOutputStream交换。如果您的代码创建了一个空文件,则无法保证当代码的调用方尝试使用该文件时,该文件仍然存在或仍然为空。将文件创建与实际使用文件分离开来会导致symlink race
也就是说,如果您想测试被测代码创建或删除文件,您必须询问文件系统,或者模拟文件系统。

使用真实的的文件系统(我会避免这样做)

使用与测试代码相同的File方法,如下所示。请注意,这是未经测试的代码,因为您没有提供MCVE

@Test
public void createsFileIfItDoesNotExist() throws InterruptedException {
    String fecha = "2023-04-26";

    String path = getFilePE(fecha);

    assertEquals(ConstantsFiles.FILE_NAME_PE + fecha + ConstantsFiles.FILE_EXTENSION, path, "wrong path");

    Thread.sleep(5 * 1000); // ms
    File expected = new File(path);
    assertTrue(expected.exists(), "should have create a file");
    assertEquals(0, expected.length(), "file should be empty");
}

一些评论:

  • 路径的Assert很像测试中的代码;我可能会在测试中硬编码路径,或者完全删除检查。但这取决于你想测试什么。
  • Thread.sleep允许文件系统反映更改。目前它的睡眠时间为5秒,这已经够糟糕的了,因为大多数测试的运行速度应该比这快得多。如果测试是不稳定的(有时通过,有时失败),您可能需要增加这个值。
  • 您可以通过使用JUnit 5的@TempDir注解(请参阅this Java Magazine blog post)来减少测试相互干扰的机会,但这需要您传入所构建路径的常量部分,而不仅仅是使用一些全局常量。
  • 对于其他测试,确保您使用不同的日期,否则一个测试可能会从另一个测试中删除文件,或者文件可能会意外存在(共享依赖项的乐趣)。

模拟文件系统

再次,未经测试的代码:

@Test
public void createsFileIfItDoesNotExist() {
    File f = mock(File.class);
    when(f.createNewFile).thenReturn(true);
    getFilePE("2023-04-26");
    verify(f).createNewFile("/expected/path/to/the/file");
}

无论你采用何种风格,都可以沿着这些路线编写更多的测试,e。例如,创建文件并向其中写入一些内容(或假装它存在),然后检查它是否被截断,或者其他任何您想要测试的内容。

相关问题