我刚开始为很多代码编写测试。有一堆类与文件系统有依赖关系,也就是它们读取CSV文件、读/写配置文件等等。
当前测试文件存储在项目的test目录中(这是一个Maven2项目),但由于种种原因,该目录并不总是存在,所以测试会失败。
你知道处理单元/集成测试中文件系统依赖的最佳实践吗?
编辑:我不是要针对上述特定问题寻求答案。那只是一个例子。我更希望得到如何处理对文件系统/数据库等的依赖的一般建议。
我刚开始为很多代码编写测试。有一堆类与文件系统有依赖关系,也就是它们读取CSV文件、读/写配置文件等等。
当前测试文件存储在项目的test目录中(这是一个Maven2项目),但由于种种原因,该目录并不总是存在,所以测试会失败。
你知道处理单元/集成测试中文件系统依赖的最佳实践吗?
编辑:我不是要针对上述特定问题寻求答案。那只是一个例子。我更希望得到如何处理对文件系统/数据库等的依赖的一般建议。
文件系统的依赖有两种类型:
/tmp
目录中。在第二种情况下,通常可以重新组织代码以消除对文件的依赖(例如,可以使用java.io.InputStream
和java.io.OutputStream
替换java.io.File
)。当然,这可能不是可能的。
您还可能需要处理文件系统中的“非确定性”(我曾经在NFS上调试过某个魔鬼般的问题)。在这种情况下,您应该在一个薄接口中包装文件系统。
最简单的方法就是编写帮助器方法,这些方法接受一个File并将调用转发到该文件:
InputStream getInputStream(File file) throws IOException {
return new FileInputStream(file);
}
您可以使用模拟对象来替换此对象,然后可以将其指向抛出异常、返回ByteArrayInputStream
或其他操作。
对于URL和URI也是如此。
有两种测试需要从文件中读取代码的选项:
将与单元测试相关的文件保存在源代码控制中(例如在测试数据文件夹中),这样任何获取最新版本并运行测试的人都可以在已知文件夹相对于测试二进制文件的位置上找到相关文件。这可能是“最佳实践”。
如果涉及的文件很大,您可能不想将它们保存在源代码控制中。在这种情况下,一个网络共享目录,可以从所有开发者和构建机器访问,可能是一个合理的折衷方案。
显然,大多数编写良好的类一开始就不会对文件系统有硬依赖。
给测试文件(包括输入和输出)命名时,应该与单元测试名称在结构上相似。
例如,在JUnit中,我会使用:
File reportFile = new File("tests/output/" + getClass().getSimpleName() + "/" + getName() + ".report.html");