我在一个大量使用IO操作的项目中引入了测试(在这种情况下是文件系统)。系统不断打开/关闭文件,检查文件是否存在,删除它们等等。
很快就会发现常规模拟不会有太多用处,因为这会使我的测试难以设置和推理。另一方面,拥有一个假的文件系统会很棒,我认为,设置起来非常简单。
红宝石家伙似乎再次这样做了,而且正是我在红宝石中要求的:http://ozmm.org/posts/fakefs.html。
Java有什么远程类似的东西吗?
答案 0 :(得分:49)
Google拥有Java 7的FileSystemProvider的开源内存实现。 project is called jimfs。
如果你使用Java 6或更早版本,还有另一种选择:我之前使用Apache Commons VFS取得了巨大的成功。它似乎很像自定义的FileSystemProvider,另一个回答者提到的是Java 7。
pre-loaded有几个文件系统实现:文件,RAM,S / FTP和Jar等等。我也见过plugin for S3。
答案 1 :(得分:35)
在Java 6及更早版本中,由于File
和FileInputStream
等类无法在Java空间中调度到不同的“虚拟文件系统”,因此很难实现。
在Java 7中,支持虚拟文件系统;见Developing a Custom File System Provider。我不知道这是否会让你做你想做的事情,但这是一个开始寻找的好地方。
咩。事实上,似乎没有任何伪文件系统,我想我将自己实现一个最小的实现。我通过使用FileSystemProvider
赢得任何东西
实际上,您通过使用FileSystemProvider获胜:
您实施的某些内容(如果在开源许可下发布)对您所在位置的其他人以及其他目的非常有用。
如果您决定切换到其他人可能正在处理的FileSystemProvider,您可以更轻松地自己。
答案 2 :(得分:12)
您可以使用JUnit包中的org.junit.rules.TemporaryFolder
:
TemporaryFolder规则允许创建在测试方法完成时保证被删除的文件和文件夹(无论是通过还是失败):
示例:强>
final TemporaryFolder testFolder = new TemporaryFolder();
testFolder.create();
final Path filePath = testFolder.newFile("input.txt").toPath();
final Path dirPath = testFolder.newFolder("subfolder").toPath();
或者退出.toPath()
部分:
final File filePath = testFolder.newFile("input.txt");
答案 3 :(得分:8)
您可以通过更改API使用File
代替OutputStream
来使用“某处编写数据”的意图来抽象File
的使用,然后传递API生产代码中的FileOutputStream
,但是从测试中传递ByteArrayOutputStream
。 ByteArrayOutputStream
是一个内存中的流,因此速度非常快,您只需使用其方法检查其内容即可 - 它非常适合测试。如果您想读取数据,还有相应的ByteArrayInputStream
。
文件系统通常非常快 - 除非你在测试中做了大量的文件I / O,否则我不会打扰。
请注意,创建java File
对象不在磁盘上创建文件,即以下代码不会导致对磁盘的任何更改:
File f = new File("somepath"); // doesn't create a file on disk
答案 4 :(得分:6)
Jimfs是内存中的NIO文件系统,非常适合测试。
答案 5 :(得分:4)
答案 6 :(得分:4)
MockFTPServer似乎有几个虚假文件系统实现(Unix / Windows)
看起来您可以从任何FTP概念中单独使用这些虚假文件系统实现。我现在正在尝试这个与您概述的完全相同的目标。
答案 7 :(得分:2)
我不确定具体的框架,但就OOP而言,一般的方法是在任何文件访问代码(接口丰富!)之上编写一些抽象层,并且可能是一个外观以便于使用常见操作。然后你只是在你正在测试的代码下面模拟一层,然后它本质上是一个虚假的文件系统(或者至少你正在测试的代码不会知道)。
如果你考虑使用依赖注入框架为你处理这个问题,它将减轻为伪造的接口实现切换组件的能力。如果您遵循控制反转的模式,将任何依赖项传递到您正在测试的类的构造函数中,这也将使测试变得容易。
public interface IFileSystem {
IFileHandle Load(string path);
//etc
}
public class ClassBeingTested {
public ClassBeingTested(IFileSystem fileSystem) {
//assign to private field
}
public void DoSomethingWithFileSystem() {
//utilise interface to file system here
//which you could easily mock for testing purposes
//by passing a fake implementation to the constructor
}
}
我希望我的java是正确的,我很久没有写过java了,但是你希望得到漂移。希望我在这里不要低估这个问题,过于简单化!
当然这都是假设您的意思是真正的单元测试,即测试尽可能小的代码单元,而不是整个系统。对于集成测试,需要采用不同的方法。
答案 8 :(得分:2)
ShrinkWrap from the Arquillian project希望在内存FileSystem中包含NIO兼容
您可以通过执行以下操作来创建简单的内存FileSystem:
FileSystem fs = ShrinkWrapFileSystems.newFileSystem(ShrinkWrap.create(GenericArchive.class))
答案 9 :(得分:1)
答案 10 :(得分:0)
我正在搜索“ Fake java FileSystem”,并发现了这个问题。不幸的是,这就是我发现的全部。所以我自己写了这个伪造的FileSystem:https://github.com/dernasherbrezon/mockfs
我正在使用它在读取/写入文件期间模拟IOExceptions。 IOException可能由于“没有磁盘空间”而发生,这几乎不可能通过其他方式进行模拟。
答案 11 :(得分:-1)
它有点旧,这个解决方案似乎只是linux,但它看起来不错 https://www.google.co.il/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=tmpfs%20on%20ubuntu
tmpfs 是内存中的映射目录(数据在重新启动时消失)。安装完成后,可以将数据复制到其中并从内存中进行处理。