如何正确地对 "abstracted" 文件处理进行单元测试?

How to properly unit test "abstracted" file handling?

我有一个 API 文件放置在某个不同的目录中,文件名由固定的 prefix/postfix 部分组成。我想抽象出这些部分,以便我的助手 class 的用户可以专注于需要完成的事情。

示例代码:

static class FileManager {
    Path getFilePath(String arg) {
        return Paths.get("/whatever", "prefix_" + arg + "_postfix");
    }

    void deleteFileIfExists(Path path) {
        if (path.toFile().exists())
            path.toFile().delete();
    }

    public void deleteFileIfExistsUsing(String arg) {
        deleteFileIfExists(getFilePath(arg));
    }
}


@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();

@Test
public void testGetFilePath() {
    assertThat(new FileManager().getFilePath("bar"), is(Paths.get("/whatever/prefix_bar_postfix")));
}

@Test
public void testDelete() throws IOException {
    File subfolder = temporaryFolder.newFolder("whatever");
    File fileToDelete = new File(subfolder, "prefix_bar_postfix");
    fileToDelete.createNewFile();
    assertThat(fileToDelete.exists(), is(true));
    new FileManager().deleteFileIfExists(fileToDelete.toPath());
    assertThat(fileToDelete.exists(), is(false));
}

如您所见,可以完全测试 getFilePath()deleteFileIfExists()。但是有没有一种有意义的方法来测试 API deleteFileIfExistsUsing(String)

我看到的唯一选择:让 另一个 class 提供基于路径的调用,然后给 FileManager 那个 class ...然后可以嘲笑。但这感觉有点矫枉过正。

那么:还有其他方法可以测试 FileManager 中的 public 方法吗?

(旁注:一个目标是单元测试在某种程度上是独立于平台的。以上实际上适用于 Linux 和 Windows 例如)

您应该模拟 path.toFile().exists() 以获得两个单元测试,一个模拟现有文件,一个模拟不存在的文件。
Stack

上的 mockito 示例

FileManager的构造函数中注入一个Function<String, Path>:

static class FileManager {
    private final Function<String, Path> pathFactory;

    FileManager(Function<String, Path> pathFactory) {
        this.pathFactory = pathFactory;
    }

    Path getFilePath(String arg) {
        return pathFactory.apply("/whatever/prefix_" + arg + "_postfix");
    }

    // ...
}

然后您可以在生产代码中注入 Paths::get,然后在测试中注入 returns 模拟 Path 的东西。