Are there any Fake File System frameworks for Java? [closed]

I am introducing tests in a project that makes heavy use of IO operations (the file system, in this case). The system constantly opens/closes files, checks if files exist, deletes them, etcetera.

It soon became obvious that regular mocking wouldn't be of much use, as that would make my tests hard to set up and reason about. On the other hand, having a fake file system would be awesome, and I think, pretty easy to set up.

It seems the ruby guys did it again, and there's exactly what I am asking for in ruby: http://ozmm.org/posts/fakefs.html.

Is there anything remotely similar for Java?


Solution 1:

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.

Solution 2:

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.

Solution 3:

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");

Solution 4:

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