marschall / memoryfilesystem

An in memory implementation of a JSR-203 file system
282 stars 36 forks source link

Is it possible to use MemoryFileSystem as the default FileSystem? #139

Closed Hakky54 closed 1 year ago

Hakky54 commented 1 year ago

I am currently writing unit tests and the to be tested class is writing files to the filesystem. I want to avoid that files are being written to any directory on the real filesystem when I just want to test and assert those files, but I am not able to find out how to configure it properly.

My use case:

To be tested class

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class App {

    public void writeTextFile() throws IOException {
        Files.write(Paths.get("/path/to/hello.txt"), "Hello World".getBytes(), StandardOpenOption.CREATE);
    }

}

I am using the same setup as shown here: https://github.com/marschall/memoryfilesystem#next-steps-junit-5

However the file is still being created on my file system, any idea what I am missing next to the Junit 5 extension?

marschall commented 1 year ago

No, the MemoryFileSystem can not be used as the default FileSystem, this would preclude Java from accessing the file actual file system. But there are other ways to achieve what you want. Check out Guidelines for Testable File Code.

In your case this may look something like this:

public class App {

    private final FileSystem fileSystem;

    App(FileSystem fileSystem) {
        this.fileSystem = fileSystem;
    }

    public App() {
        this(FileSystems.getDefault());
    }

    public void writeTextFile() throws IOException {
        Files.writeString(this.fileSystem.resolve("/path/to/hello.txt"), "Hello World", StandardCharsets.US_ASCII, StandardOpenOption.CREATE);
    }

}

And then have a test like this

class AppTests {

    @Test
    void writeTextFile() throws IOException {
        try (FileSystem fileSystem = MemoryFileSystemBuilder.newEmpty().build()) {
            App app = new App(fileSystem);
            app.writeTextFile();
            Path output = fileSystem.resolve("/path/to/hello.txt");
        }
    }

}

Instead of injecting a FileSystem into App you can also inject a Path.

Hakky54 commented 1 year ago

Thank you it is clear how I can test this kind of use case while using the memory file system, the examples helps a-lot.

marschall commented 1 year ago

You're welcome