21

我刚开始为很多代码编写测试。有一堆依赖于文件系统的类,即它们读取 CSV 文件、读/写配置文件等等。

目前,测试文件存储在项目的测试目录中(它是一个 Maven2 项目),但由于多种原因,该目录并不总是存在,因此测试失败。

你知道在单元/集成测试中处理文件系统依赖的最佳实践吗?

编辑:我不是在寻找我上面描述的那个特定问题的答案。那只是一个例子。我更喜欢一般建议如何处理对文件系统/数据库等的依赖关系。

4

5 回答 5

25

第一个应该尽量让单元测试远离文件系统- 请参阅这套单元测试规则。如果可能的话,让您的代码使用 Streams,这些 Streams 将作为单元测试的缓冲区(即在内存中),并在生产代码中使用 FileStream。

如果这不可行,您可以让您的单元测试生成他们需要的文件。这使得测试易于阅读,因为所有内容都在一个文件中。这也可以防止权限问题。

您可以在单元测试中模拟文件系统/数据库/网络访问。

您可以将依赖数据库或文件系统的单元测试视为集成测试。

于 2008-12-18T10:30:12.083 回答
2

对文件系统的依赖有两种形式:

  • 您的测试所依赖的文件;如果您需要文件来运行测试,那么您可以在测试中生成它们并将它们放在一个/tmp目录中。
  • 您的代码所依赖的文件:配置文件或输入文件。

在第二种情况下,通常可以重新构建代码以删除对文件的依赖(例如 java.io.File 可以替换为java.io.InputStreamandjava.io.OutputStream等)。这当然是不可能的。

您可能还需要处理文件系统中的“非确定性”(我曾经在 NFS 上调试过一些东西)。在这种情况下,您可能应该将文件系统包装在一个瘦接口中。

在最简单的情况下,这只是获取 File 并将调用转发到该文件的辅助方法:

InputStream getInputStream(File file) throws IOException {
    return new FileInputStream(file);
}

然后,您可以用一个 mock 替换这个,您可以指导它抛出异常,或返回 aByteArrayInputStream或其他任何东西。

URL 和 URI 也是如此。

于 2008-12-18T10:47:45.323 回答
1

测试需要从文件中读取的代码有两个选项:

  1. 将与单元测试相关的文件保存在源代码控制中(例如,在测试数据文件夹中),因此任何获取最新版本并运行测试的人始终将相关文件保存在相对于测试二进制文件的已知文件夹中。这可能是“最佳实践”。

  2. 如果有问题的文件很大,您可能不想将它们保留在源代码管理中。在这种情况下,所有开发人员和构建机器都可以访问的网络共享可能是一个合理的折衷方案。

显然,大多数编写良好的类首先不会对文件系统有硬依赖。

于 2008-12-18T10:19:44.770 回答
0

为 in 和 out 的测试文件指定在结构上与单元测试名称相似的名称。

例如,在 JUnit 中,我会使用:

File reportFile = new File("tests/output/" + getClass().getSimpleName() + "/" + getName() + ".report.html");
于 2009-02-04T09:30:57.790 回答
0

通常,文件系统测试不是很关键:文件系统易于理解,易于设置并保持稳定。此外,访问通常非常快,因此本身没有理由回避它或模拟测试。

我建议您找出该目录不存在的原因并确保它存在。例如,在 setUp() 中检查文件或目录是否存在,如果检查失败,则复制文件。这只会发生一次,因此对性能的影响很小。

于 2008-12-18T10:15:09.773 回答