我刚开始为很多代码编写测试。有一堆依赖于文件系统的类,即它们读取 CSV 文件、读/写配置文件等等。
目前,测试文件存储在项目的测试目录中(它是一个 Maven2 项目),但由于多种原因,该目录并不总是存在,因此测试失败。
你知道在单元/集成测试中处理文件系统依赖的最佳实践吗?
编辑:我不是在寻找我上面描述的那个特定问题的答案。那只是一个例子。我更喜欢一般建议如何处理对文件系统/数据库等的依赖关系。
我刚开始为很多代码编写测试。有一堆依赖于文件系统的类,即它们读取 CSV 文件、读/写配置文件等等。
目前,测试文件存储在项目的测试目录中(它是一个 Maven2 项目),但由于多种原因,该目录并不总是存在,因此测试失败。
你知道在单元/集成测试中处理文件系统依赖的最佳实践吗?
编辑:我不是在寻找我上面描述的那个特定问题的答案。那只是一个例子。我更喜欢一般建议如何处理对文件系统/数据库等的依赖关系。
对文件系统的依赖有两种形式:
/tmp
目录中。在第二种情况下,通常可以重新构建代码以删除对文件的依赖(例如 java.io.File 可以替换为java.io.InputStream
andjava.io.OutputStream
等)。这当然是不可能的。
您可能还需要处理文件系统中的“非确定性”(我曾经在 NFS 上调试过一些东西)。在这种情况下,您可能应该将文件系统包装在一个瘦接口中。
在最简单的情况下,这只是获取 File 并将调用转发到该文件的辅助方法:
InputStream getInputStream(File file) throws IOException {
return new FileInputStream(file);
}
然后,您可以用一个 mock 替换这个,您可以指导它抛出异常,或返回 aByteArrayInputStream
或其他任何东西。
URL 和 URI 也是如此。
测试需要从文件中读取的代码有两个选项:
将与单元测试相关的文件保存在源代码控制中(例如,在测试数据文件夹中),因此任何获取最新版本并运行测试的人始终将相关文件保存在相对于测试二进制文件的已知文件夹中。这可能是“最佳实践”。
如果有问题的文件很大,您可能不想将它们保留在源代码管理中。在这种情况下,所有开发人员和构建机器都可以访问的网络共享可能是一个合理的折衷方案。
显然,大多数编写良好的类首先不会对文件系统有硬依赖。
为 in 和 out 的测试文件指定在结构上与单元测试名称相似的名称。
例如,在 JUnit 中,我会使用:
File reportFile = new File("tests/output/" + getClass().getSimpleName() + "/" + getName() + ".report.html");
通常,文件系统测试不是很关键:文件系统易于理解,易于设置并保持稳定。此外,访问通常非常快,因此本身没有理由回避它或模拟测试。
我建议您找出该目录不存在的原因并确保它存在。例如,在 setUp() 中检查文件或目录是否存在,如果检查失败,则复制文件。这只会发生一次,因此对性能的影响很小。