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

dev*_*ium 82 java testing unit-testing mocking

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

显而易见的是,定期模拟不会有太大用处,因为这会使我的测试难以设置和推理.另一方面,拥有一个假的文件系统会很棒,我认为,设置起来非常简单.

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

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

Mic*_*uff 51

Google拥有Java 7的FileSystemProvider的开源内存实现.该项目称为jimfs.


如果你使用Java 6或更早版本,还有另一种选择:我之前使用过Apache Commons VFS取得了巨大的成功.它似乎与自定义FileSystemProvider非常相似,提到的另一个回答者是Java 7.

预先加载了几个文件系统实现:文件,RAM,S/FTP和Jar等等.我也看过S3插件.

  • +1到jimfs,这让我可以在没有一次更改的情况下测试我的代码.(我偶然使用了`Path`) (6认同)

Ste*_*n C 35

在Java 6及更早版本中,它很难,因为类不喜欢File并且FileInputStream无法在Java空间中分派到不同的"虚拟文件系统".

在Java 7中,支持虚拟文件系统; 看到开发自定义文件系统供应商.我不知道这是否会让你做你想做的事,但这是一个开始寻找的好地方.


咩.事实上,似乎没有任何伪文件系统,我想我将自己实现一个最小的实现.我通过使用FileSystemProvider赢得任何东西

实际上,你通过使用FileSystemProvider获胜:

  • 您实现的东西(如果在开源许可下发布)对您所在位置的其他人以及其他目的非常有用.

  • 如果您决定切换到其他人可能正在进行的FileSystemProvider,您可以更轻松地自己.

  • 至少它**允许**你这样做.就像你自己说的那样 - *"设置起来很容易"*. (6认同)
  • +1用于推荐编写和开源解决方案 (2认同)

tho*_*ork 16

您可以使用org.junit.rules.TemporaryFolderJUnit的包:

TemporaryFolder规则允许创建在测试方法完成时保证删除的文件和文件夹(无论是通过还是失败):

例:

final TemporaryFolder testFolder = new TemporaryFolder();
testFolder.create();
final Path filePath = testFolder.newFile("input.txt").toPath();
final Path dirPath = testFolder.newFolder("subfolder").toPath();
Run Code Online (Sandbox Code Playgroud)

或者退出.toPath()部分:

final File filePath = testFolder.newFile("input.txt");
Run Code Online (Sandbox Code Playgroud)

  • TemporaryFolder 不在内存中。 (2认同)

Boh*_*ian 8

您可以File通过使用"在某处编写数据"的意图来抽象使用,通过更改API来使用OutputStream而不是a File,然后FileOutputStream在生产代码中传递API ,但是ByteArrayOutputStream从测试中传递它.A ByteArrayOutputStream是一个内存中的流,所以它非常快,您只需使用其方法检查其内容 - 它非常适合测试.ByteArrayInputStream如果你想读取数据,还有相应的.

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

请注意,创建Java File对象并不会在磁盘上创建一个文件,即下面的代码不会导致任何改变磁盘:

File f = new File("somepath"); // doesn't create a file on disk
Run Code Online (Sandbox Code Playgroud)


pro*_*ron 6

谷歌的Jimfs是一个内存NIO文件系统,非常适合测试.


Wic*_*ams 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
   }
}
Run Code Online (Sandbox Code Playgroud)

我希望我的java是正确的,我已经很长一段时间没有写java了,但希望你能明白其中的意思。希望我没有低估这里的问题并且过于简单化!

当然,这一切都假设您的意思是真正的单元测试,即测试尽可能小的代码单元,而不是整个系统。对于集成测试,需要不同的方法。