How to properly unit test "abstracted" file handling?

GhostCat salutes Monica C. :

I have an API where file are placed in some distinct directory, and file names are made up of fixed prefix/postfix parts. I want to abstract away those parts, so that users of my helper class can focus on what needs to be done.

Example code:

static class FileManager {
    Path getFilePath(String arg) {
        return Paths.get("/whatever", "prefix_" + arg + "_postfix");
    }

    void deleteFileIfExists(Path path) {
        if (path.toFile().exists())
            path.toFile().delete();
    }

    public void deleteFileIfExistsUsing(String arg) {
        deleteFileIfExists(getFilePath(arg));
    }
}


@Rule
public TemporaryFolder temporaryFolder = new TemporaryFolder();

@Test
public void testGetFilePath() {
    assertThat(new FileManager().getFilePath("bar"), is(Paths.get("/whatever/prefix_bar_postfix")));
}

@Test
public void testDelete() throws IOException {
    File subfolder = temporaryFolder.newFolder("whatever");
    File fileToDelete = new File(subfolder, "prefix_bar_postfix");
    fileToDelete.createNewFile();
    assertThat(fileToDelete.exists(), is(true));
    new FileManager().deleteFileIfExists(fileToDelete.toPath());
    assertThat(fileToDelete.exists(), is(false));
}

As you can see, it is possible to fully test getFilePath() and deleteFileIfExists(). But is there a meaningful way to test the one API deleteFileIfExistsUsing(String)?

The only option I see: have another class that provides the Path-based calls, and then give the FileManager an instance of that class ... that could then be mocked. But that feels a bit like overkill.

So: are the other ways to test the public method from FileManager?

( side note: one goal is that the unit test is somehow platform independent. The above actually works on Linux and Windows for example )

Andy Turner :

Inject a Function<String, Path> into the constructor of FileManager:

static class FileManager {
    private final Function<String, Path> pathFactory;

    FileManager(Function<String, Path> pathFactory) {
        this.pathFactory = pathFactory;
    }

    Path getFilePath(String arg) {
        return pathFactory.apply("/whatever/prefix_" + arg + "_postfix");
    }

    // ...
}

Then you can inject Paths::get in production code, and something that, say, returns mock Paths in tests.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=141015&siteId=1