Skip to content

How to mock a Files static method with Mockito

I have a method in my utilities:

public void createDirectories(final Path root, final Scaffolding scaffolding) throws FileAlreadyExistsException {
    if (Files.exists(root)) {
        throw new FileAlreadyExistsException("Root directory " + root.toString() + " already exists.");
    } else {
        Files.createDirectories(root);
        // Create directories from the scaffolding object
    }
}

I want to mock Files so I can test to make sure Files.createDirectories with the expected fields are called or not.

Can I do this with Mockito? Or do I need to actually create the directories and check for their existence in some tmp folder?

Answer

When you write something with tdd and have troubles consider it as signal of bad design. You don’t need to mock static fields or find some tricky lib for do it. Instead of doing this make entity that represent filesystem and place all methods related to file operations to this class. With this refactor your code will be like that:

class UtilClass { //util classes are bad don't do it
    private final FileSystem fileSystem;

    public UtilClass(FileSystem fileSystem) {
        this.fileSystem = fileSystem;
    }


    public void createDirectories(final Path root, final Scaffolding scaffolding) throws FileAlreadyExistsException {
        if (fileSystem.exists(root)) {
            throw new FileAlreadyExistsException("Root directory " + root.toString() + " already exists.");
        } else {
            fileSystem.createDirectories(root);
            // Create directories from the scaffolding object
    }




interface FileSystem {

    boolean exists(Path path);

    void createDirectories(Path path);
}

and test class

class UtilClassTest {


        @Test(expected = FileAlreadyExistsException.class)
        public void shouldThrowExceptionWhenRootPathExists() {
            FileSystem mockFileSystem = Mockito.mock(FileSystem.class);
            Mockito.when(mockFileSystem.exists(anyPath())).return(true);
            UtilClass util = new UtilClass(mockFileSystem);
            util.createDirectories(mock(Path.class), mock(Scaffolding.class))
        }
    }

In your code outside tests replace mock to implementation.

class FileSystemImpl implements FileSystem {

    boolean exists(Path path){
        return Files.exists(path);
    }

    createDirectories(Path path){
        return Files.createDirectories(path);
    }

} 

and you don’t need to touch file system in tests or mock static fields.