有没有用于 Java 的伪文件系统框架?

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

很快就发现,常规的嘲笑没有多大用处,因为这会使我的测试难以设置和推理。另一方面,有一个假的文件系统将是非常棒的,我认为,非常容易设置。

看来红宝石的家伙又这么做了,这正是我想要的红宝石: http://ozmm.org/posts/fakefs.html

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

33878 次浏览

i'm not sure about specific frameworks, but a general approach in terms of OOP would be to write some abstracted layers on top of any file access code (interfaces galore!) and perhaps a facade to ease use of common operations. then you just mock one layer below the code you are currently testing and it then essentially a fake file system (or at least the code you're testing won't know otherwise).

if you look into using a dependency injection framework to handle this for you it will ease the ability to switch out components for a faked implementation of an interface. if you follow the patterns of inversion of control, passing in any dependencies into the constructor of the class you are testing this will also make for easy testing.

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
}
}

i hope my java is correct, i haven't written java in a long while, but you will hopefully get the drift. hopefully i'm not underestimating the issue here and being overly simplistic!

of course this is all assuming you mean true unit testing, that is, testing the smallest possible units of code, and not an entire system. for integration testing a different approach is needed.

A simple way would be to use your system's way of providing a file system based totally on RAM - tempfs on Linux, a RAM disk on Windows.

You can abstract the use of File by using the intention of "somewhere to write data" by changing your API to use an OutputStream instead of a File, then pass the API a FileOutputStream in your production code, but pass it a ByteArrayOutputStream from your tests. A ByteArrayOutputStream is an in-memory stream, so it's very fast and you can simply inspect its contents by using its methods - it's perfect for testing. There's also the corresponding ByteArrayInputStream if you want to read data.

File systems are generally pretty fast - unless you were doing a great deal of File I/O in your tests, I wouldn't bother.

Note that creating a java File object does not create a file on disk, ie the following code doesn't cause any change to disk:

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

In Java 6 and earlier it is difficult because classes like File and FileInputStream provide no way to dispatch to different "virtual file systems" in Java space.

In Java 7, there is support for virtual file systems; see Developing a Custom File System Provider. I don't know whether this will allow you to do what you want to do, but it is a good place to start looking.


Meh. Being the fact that there doesn't seem to actually be any fake file system, I guess I'll just implement a minimal implementation by myself. I win nothing by using FileSystemProvider

Actually, you DO win by using FileSystemProvider:

  • You implement something that (if released under an open source license) could be very useful to other people in your position, and for other purposes.

  • You make it easier for yourself if you decide to switch to a FileSystemProvider that someone else might be working on right now.

MockFTPServer appears to have a couple of Fake Filesystem implementations (Unix/Windows)

It looks like you can use these fake filesystem implementations quite seperately from any FTP concepts. I'm trying this now for exactly the same pursposes as you've outlined.

Google has an open-source, in-memory implementation of Java 7's FileSystemProvider. The project is called jimfs.


If you use Java 6 or earlier, there is an alternative: I've used Apache Commons VFS before to great success. It seems to be much like the custom FileSystemProvider another answerer mentioned is in Java 7.

It comes pre-loaded with several file-system implementations: File, RAM, S/FTP, and Jar to name a few. I've also seen a plugin for S3.

ShrinkWrap from the Arquillian project looks to include a NIO compliant in memory FileSystem

You can create a simple in memory FileSystem by doing the following:

FileSystem fs = ShrinkWrapFileSystems.newFileSystem(ShrinkWrap.create(GenericArchive.class))

You can use org.junit.rules.TemporaryFolder from the JUnit package:

The TemporaryFolder Rule allows creation of files and folders that are guaranteed to be deleted when the test method finishes (whether it passes or fails):

Example:

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

Alternatively quit the .toPath() part:

final File filePath = testFolder.newFile("input.txt");

Jimfs, by Google, is an in memory NIO filesystem, that's great for tests.

Two other in memory file systems for java are,

memoryfilesystem

ephemeralfs

Both implement the NIO.2 File system api.

Its a bit old and this solution seems to be linux only but it looks good https://www.google.co.il/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=tmpfs%20on%20ubuntu

tmpfs is an in-memory mapped directory (data disappears on reboot). Once mounted, Data can be copied into it and be worked on from memory.

I was googling "Fake java FileSystem" and found this question. Unfortunately this is all I found. So I wrote this fake FileSystem myself: https://github.com/dernasherbrezon/mockfs

I'm using it for simulating IOExceptions during read/write to files. IOException could happen for example due to "no disk space", which is nearly impossible to simulate by other means.