【问题标题】:How to properly unit test "abstracted" file handling?如何正确地对“抽象”文件处理进行单元测试?
【发布时间】:2019-09-02 07:42:28
【问题描述】:

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

示例代码:

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)

我看到的唯一选择:有 another 类提供基于路径的调用,然后给FileManager 一个该类的实例......然后可以模拟。但这感觉有点矫枉过正。

那么:还有其他方法可以测试来自FileManager 的公共方法吗?

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

【问题讨论】:

    标签: java file unit-testing junit temporary-files


    【解决方案1】:

    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,比如在测试中返回模拟Paths。

    【讨论】:

    • 在您使用BiFunction 时,我可能倾向于定义一个特定的接口PathFactory:这两个参数的含义真的不清楚。
    • 对不起,前后左右。您的评论完全有道理,所以我回滚到原始内容。
    【解决方案2】:

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

    【讨论】:

    • path 是一个参数,在我的例子中,相应的 Path 对象是在生产代码创建的。我不明白怎么能嘲笑那个对象。这就是我问题的重点。
    • 你检查过post
    • 我知道在嘲笑此类事情时应该谨慎。但最后,我确实有必须读取/删除特定文件的生产代码,我想确保我有单元测试很好地涵盖了这一点。
    猜你喜欢
    • 1970-01-01
    • 2017-06-26
    • 2011-12-19
    • 2022-07-25
    • 2020-01-06
    • 2010-09-23
    • 2014-01-30
    • 2011-02-02
    • 1970-01-01
    相关资源
    最近更新 更多