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