我刚开始为很多代码编写测试。有一堆类依赖于文件系统,即读取CSV文件,读/写配置文件等。
目前测试文件存储在项目的测试目录中(它是Maven2项目),但由于多种原因,该目录并不总是存在,因此测试失败。
您是否了解在单元/集成测试中应对文件系统依赖性的最佳实践?
编辑:我没有在上面描述的具体问题中找到答案。那只是一个例子。我更喜欢如何处理文件系统/数据库等依赖项的一般建议。
答案 0 :(得分:24)
首先应该尝试使单元测试远离文件系统 - 请参阅此Set of Unit Testing Rules。如果可能,您的代码使用Streams,它们将是单元测试的缓冲区(即内存中)和生产代码中的FileStream。
如果这不可行,您可以让单元测试生成他们需要的文件。这使得测试易于阅读,因为所有内容都在一个文件中。这也可能会阻止权限问题。
您可以在单元测试中 mock 文件系统/数据库/网络访问权限。
您可以将依赖于DB或文件系统的单元测试视为集成测试。
答案 1 :(得分:2)
文件系统的依赖关系有两种:
/tmp
目录中。 在第二种情况下,通常可以重新构造代码以消除对文件的依赖(例如,java.io.File可以替换为java.io.InputStream
和java.io.OutputStream
等。)当然,这可能是不可能的。
您可能还需要在文件系统中处理“非确定性”(我曾经在NFS上调试过一次作业的恶魔)。在这种情况下,您应该将文件系统包装在瘦接口中。
最简单的说,这只是一个辅助方法,它接受一个文件并将调用转发到该文件:
InputStream getInputStream(File file) throws IOException {
return new FileInputStream(file);
}
然后,您可以使用模拟替换此模型,您可以直接将其抛出异常,或者返回ByteArrayInputStream
或其他任何内容。
对于URL和URI也是如此。
答案 2 :(得分:1)
有两种方法可以测试需要从文件中读取的代码:
将与单元测试相关的文件保存在源代码管理中(例如,在测试数据文件夹中),因此获取最新版本并运行测试的任何人都会在相对于测试二进制文件的已知文件夹中包含相关文件。这可能是“最佳做法”。
如果相关文件很大,您可能不希望将它们保留在源代码管理中。在这种情况下,可从所有开发人员和构建计算机访问的网络共享可能是一种合理的妥协。
显然,大多数编写良好的类首先都不会对文件系统产生硬依赖。
答案 3 :(得分:0)
通常,文件系统测试不是很关键:文件系统易于理解,易于设置和保持稳定。此外,访问通常非常快,因此本身没有理由避免它或模拟测试。
我建议您找出目录不存在的原因,并确保它确实存在。例如,检查setUp()中是否存在文件或目录,如果检查失败则复制文件。这只发生一次,因此性能影响很小。
答案 4 :(得分:0)
提供输入和输出的测试文件,这些文件在结构上与单元测试名称类似。
例如,在JUnit中,我使用:
File reportFile = new File("tests/output/" + getClass().getSimpleName() + "/" + getName() + ".report.html");