Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should I create wrapper for java.nio.Files for Unit test purpose?

I am trying to write unit test for below class without creating real file

public class TempFileWritter{
    public String writeToTempFile(byte[] value) throws IOException {
        Path tempFile = Files.createTempFile(dir, prefix, suffix);
        Files.write(tempFile, value);
        return tempFile.toAbsolutePath().toString();
    }
}

I am using Mockito that cannot mock static method. So that my current solution is writing a wrapper class for java.nio.Files class and the I can inject it to the my class as below:

MyAppFileUtils class:

public class MyAppFileUtils {

    public void write(Path file, byte[] value) throws IOException {
        Files.write(file, value);
    }

    public Path createTempFile(Path dir, String prefix, String suffix) throws IOException {
        return Files.createTempFile(dir, prefix, suffix);
    }
}

The modified class is:

public class TempFileWritter{
    MyAppFileUtils fileUtils;
    public void setFileUtils(MyAppFileUtils fileUtils) {
        this.fileUtils = fileUtils;
    }
    public String writeToTempFile(byte[] value) throws IOException {
        Path tempFile = fileUtils.createTempFile(dir, prefix, suffix);
        fileUtils.write(tempFile, value);
        return tempFile.toAbsolutePath().toString();
    }
}

Someone agrue that creating class MyAppFileUtils is redundant because it don't do anything except calling method in class java.nio.Files. Could you give me some advices about that?

like image 880
Nghia Avatar asked Jun 27 '16 10:06

Nghia


People also ask

What is Java NIO files?

Advertisements. Java NIO package provide one more utility API named as Files which is basically used for manipulating files and directories using its static methods which mostly works on Path object.

Which methods are found in the NIO 2 files class?

Java NIO Files class contains static methods that is used for manipulating files and directories and those methods mostly works on Path object.


1 Answers

Use JimFs an in-memory implementation of the Java 7 filesystem API. You will need to make sure that your code allows for alternative filesystem implementations, but it should result in more extendable code and its much more preferable to mocking.

Let's say your class looks like

public class TempFileWriter {

    private final Path tempDir;
    private final String prefix;
    private final String suffix;

    public TempFileWriter(Path tempDir, String prefix, String suffix) {
        this.tempDir = tempDir;
        this.prefix = prefix;
        this.suffix = suffix;
    }

    public Path writeToTempFile(byte[] value) throws IOException {
        Path tempFile = Files.createTempFile(tempDir, prefix, suffix);
        Files.write(tempFile, value);
        return tempFile;
    }
}

Your unit test could be

@Test
public void testCreateTempFile() throws IOException {
    FileSystem fs = Jimfs.newFileSystem();

    Path tempDir = fs.getPath("mytempdir");
    String prefix = "myprefix";
    String suffix = ".tmp";

    byte[] data = new byte[1];
    data[0] = 0x66;

    TempFileWriter tempFileWriter = new TempFileWriter(tempDir, prefix, suffix);
    tempFileWriter.writeToTempFile(data);

    Files.list(tempDir).forEach(path -> {
        String fileName = path.getName(0).toString();
        assertTrue(fileName.startsWith(prefix));
        assertTrue(fileName.endsWith(suffix));
        assertTrue(Files.readAllBytes(path)[0] == 0x66)
    });
}

Your code is now more extendable, because you can use different filesytem implementations. Your unit test is improved because you don’t need to mock anything.

like image 90
Magnus Avatar answered Oct 10 '22 04:10

Magnus