文件解析和翻译的单元测试

Unit tests for file parsing and translation

如何为以下方法编写单元测试 - 使其与输入文件无关?

似乎读取和转换为业务对象是不同的职责——需要分开。

这将使业务翻译成为可测试的。

欢迎提出任何建议。

    public Map<header,record> createTradeFeedRecords(String tradeFile,String config) throws Exception {
        Map<header,record>  feedRecordMap = 
                new LinkedHashMap<>();
        try (BufferedReader reader = new BufferedReader(new FileReader(tradeFile))) {
            for (String line; (line = reader.readLine()) != null;) {
                if (line.trim().isEmpty() || line.startsWith("#") )
                    continue;

                Record record = recordParser.extractTradeFeedRecord(line,config):
                feedRecordMap .put(record.getHeader(), record) ;

            }
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        } finally {

        }
        return feedRecordMap ;
    }

您可以使用 JUnit TemporaryFolder rule (or, if using JUnit5, its equivalent extension) 为您的测试创建一个输入文件。然后,您将在 tradeFile 参数中提供该文件的路径,您的测试将对您创建的文件进行操作。在测试完成后JUnit会丢弃临时文件夹,从而坚持自包含的测试原则。

我认为,这是最接近 createTradeFeedRecords 方法的 实际 行为的方法。

但是,如果您真的不想在测试中使用文件系统,或者您确实只是想实现这一点..

It seems that the reading and translation into business objects are distinct responsibilities - which need to be separate.

... 然后您可以提取接口后面的 new FileReader(tradeFile) 调用。可能是这样的:

public interface TradeReader {
    Reader read(String input);
}

'normal' 的实现是:

public class FileTradeReader implements TradeReader {
    @Override
    public Reader read(String input) {
        return new FileReader(input);
    }
}

然后您可以提供此实现以用于您的测试用例:

public class StubTradeReader implements TradeReader {
    @Override
    public Reader read(String input) {
        return new StringReader(input);
    }
}

在你的测试中,你将注入 class-under-test(即包含 createTradeFeedRecords 的 class)和 StubTradeReader 的实例。这样,在您的测试中调用的 createTradeFeedRecords 方法将根据您在创建 StubTradeReader 时提供的任何输入起作用,并且您的测试不会与文件系统进行交互。

您也可以单独测试TradeReader(也许使用上面概述的临时文件夹方法),从而实现分离阅读和翻译并独立测试的目标。