【问题标题】:How to unit test a method that reads a given file如何对读取给定文件的方法进行单元测试
【发布时间】:2014-01-09 19:23:44
【问题描述】:

我知道这有点幼稚。如何在不提供物理文件作为输入的情况下对这段代码进行单元测试。 我是 mockito 和单元测试的新手。所以我不确定。请帮忙。

public static String fileToString(File file) throws IOException
{
    BufferedReader br = new BufferedReader(new FileReader(file));
    try {
        StringBuilder sb = new StringBuilder();
        String line = br.readLine();

        while (line != null) {
            sb.append(line);
            sb.append("\n");
            line = br.readLine();
        }
        return sb.toString();
    } finally {
        br.close();
    }
}

【问题讨论】:

标签: java file unit-testing junit mockito


【解决方案1】:

您可以创建一个文件作为测试的一部分,无需模拟它。

JUnit 确实有一个很好的功能,可以创建用于测试的文件并使用TemporaryFolder 规则自动清理它们。

public class MyTestClass {

    @Rule
    public TemporaryFolder folder = new TemporaryFolder();

    @Test
    public void myTest() {
        // this folder gets cleaned up automatically by JUnit
        File file = folder.newFile("someTestFile.txt");

        // populate the file
        // run your test
    }
}

【讨论】:

  • 但是不读取物理文件这不是违反单元测试的最佳实践吗?
  • 不,我不会这么说。我认为使用真实对象没有问题,尤其是当它使测试变得更加容易时。对于像 File 这样的对象,它几乎在每个 Java 应用程序中都经过了严格测试和使用(因此它可能工作得很好)并且具有与之相关的各种操作系统特定的东西,使用真实文件没有害处。
【解决方案2】:

你或许应该重构你的方法。正如您所意识到的,将文件作为输入的方法不容易测试。此外,它似乎是静态的,这无助于可测试性。如果您将方法重写为:

public String fileToString(BufferedReader input) throws IOException

它会更容易测试。您将业务逻辑与读取文件的技术分开。据我了解,您的业务逻辑是读取流并确保行尾是 unix 样式。

如果你这样做,你的方法将是可测试的。您还可以使其更通用:它现在可以从文件、URL 或任何类型的流中读取。更好的代码,更容易测试...

【讨论】:

  • 该方法只使用一次,也只在类内使用。它是否使它成为使其成为静态的良好候选者。
  • 那么,将其设为私有而不对其进行测试,而不是使其成为静态的,这是一个很好的候选。您的测试应该与实现无关,但要测试被测单元的行为(大部分时间是一个类)。
  • 我不明白你的建议是否使用 bufferedreader 我可以模拟 bufferedreader 输入还是我可以轻松地将内容添加到缓冲阅读器,所以我可以测试它而不是文件输入。
  • 要实现 100% 的代码覆盖率,还需要测试私有方法。
  • 您可以在 StringReader 的帮助下轻松地在内存中完全创建一个 BufferedReader,而无需依赖于 File。
【解决方案3】:

为什么要模拟文件?嘲笑java.io.File 是个坏主意,因为它有很多原生的东西。我建议您确保在运行单元测试时在类路径中提供一个极简文本文件。您可以将此文件转换为文本并确认输出。

【讨论】:

  • 谢谢。但是,不读取物理文件不是违反单元测试的最佳实践吗?
  • 不。我不这么认为。单元测试的重点是在“功能单元”中编写代码,然后使用小样本输入测试每个单元 - 并验证您是否为这个小样本输入获得了正确的输出。
【解决方案4】:

您可以结合使用 ByteArrayInputStream 和 BufferedReader 类,在代码中创建所需的文件。所以没有必要在你的系统上创建一个真正的文件。如果您没有足够的权限(基于某些特定情况)来创建文件,会发生什么情况。在下面的代码中,您可以创建自己想要的文件内容:

public static void main(String a[]){

    String str = "converting to input stream"+
                    "\n and this is second line";
    byte[] content = str.getBytes();
    InputStream is = null;
    BufferedReader bfReader = null;
    try {
        is = new ByteArrayInputStream(content);
        bfReader = new BufferedReader(new InputStreamReader(is));
        String temp = null;
        while((temp = bfReader.readLine()) != null){
            System.out.println(temp);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try{
            if(is != null) is.close();
        } catch (Exception ex){

        }
    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-12
    • 1970-01-01
    • 1970-01-01
    • 2022-11-17
    • 2021-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多