是否有适用于Java的虚假文件系统框架?

时间:2011-08-07 01:47:08

标签: java unit-testing testing mocking

我在一个大量使用IO操作的项目中引入了测试(在这种情况下是文件系统)。系统不断打开/关闭文件,检查文件是否存在,删除它们等等。

很快就会发现常规模拟不会有太多用处,因为这会使我的测试难以设置和推理。另一方面,拥有一个假的文件系统会很棒,我认为,设置起来非常简单。

红宝石家伙似乎再次这样做了,而且正是我在红宝石中要求的:http://ozmm.org/posts/fakefs.html

Java有什么远程类似的东西吗?

12 个答案:

答案 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及更早版本中,由于FileFileInputStream等类无法在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,但是从测试中传递ByteArrayOutputStreamByteArrayOutputStream是一个内存中的流,因此速度非常快,您只需使用其方法检查其内容即可 - 它非常适合测试。如果您想读取数据,还有相应的ByteArrayInputStream

文件系统通常非常快 - 除非你在测试中做了大量的文件I / O,否则我不会打扰。

请注意,创建java File对象在磁盘上创建文件,即以下代码不会导致对磁盘的任何更改:

File f = new File("somepath"); // doesn't create a file on disk

答案 4 :(得分:6)

谷歌的

Jimfs是内存中的NIO文件系统,非常适合测试。

答案 5 :(得分:4)

一种简单的方法是使用系统提供完全基于RAM的文件系统 - 在Linux上tempfs,在Windows上RAM disk

答案 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)

java的内存文件系统中的另外两个是

memoryfilesystem

ephemeralfs

两者都实现了NIO.2文件系统API。

答案 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 是内存中的映射目录(数据在重新启动时消失)。安装完成后,可以将数据复制到其中并从内存中进行处理。