Java: 如何对在方法范围内创建和操作文件的方法进行单元测试?

Java: How do I unit test a method that creates and manipulates a file within the scope of the method?

我正在使用 JUnit 和 JMockit 创建一个单元测试方法来测试 CSV 文件的创建和操作。如何拦截正在创建的文件以确保创建正确?

@Test
public void testPersistResultsAsCSV() throws IOException {
    final Long id = new Long(1234l);

    TableRow row = new TableRow();
    row.setValue(317l);
    row.setId(1234l);

    final List<TableRow> rows = new ArrayList<TableRow>();
    rows.add(row);

    final List<TableRow> empty = new ArrayList<TableRow>();

    new Expectations() {
        {
            tableService.findTableRowsById(id, (TableQueryOptions)any);
            result = rows;

            tableService.findTableRowsById(id, (TableQueryOptions)any);
            result = empty;

            fileDataService.saveResultsFile((ResultsFile) any);

        }
    };

    resultsToCsvService.persistResultsAsCSV(id);

}

可能应该使用规则(有史以来最愚蠢的名称,实际上与规则本身无关)。

Rules for Files in Unit Tests

您应该重构被测方法,以便为它提供输出流或编写器,而不是让它自己打开文件。这通常是一个好主意,即使在单元测试的上下文之外,因为它使代码更可重用;例如,您可能希望将输出写入套接字或压缩流。

我是 JMockit 的创造者,但我很乐意为此说 "don't use JMockit"。

可以 模拟 Java IO 类,但这几乎不是一个好主意;相反,使用本地文件系统上的真实文件。你的测试会更简单,更不脆弱,并且足够快(除非你做了一些坏事,比如 reading/writing 大文件,大量文件,或者访问一个缓慢的远程目录 - 但这些应该发生 none在编写良好的测试中)。

当人们模拟 IO API(即,FileFileWriter 等)时,他们不可避免地以与代码实现紧密耦合的测试结束正在测试中,因此复杂而脆弱。实际上,让测试接触文件系统会更好;如果这使它成为 "integration test",那就这样吧。