0

I have an existing Java class that writes to a file.

public final class WriteToFile{

    private Writer file_writer;
    private static final String encoding_format = "UTF8";
    private FileWrite(final File fpath) throws IOException {
        this.file_writer = new OutputStreamWriter(new FileOutputStream(fpath), encoding_format);
    }

    @Override
    public void fileWrite(final String msg) {
        try {
            this.file_writer.write(msg);
            this.file_writer.write("\n");
            this.file_writer.flush();
        this.file_writer.close();
        } catch (IOException e) {
            log.error("File write failed", e);
        }
    }

    }

In order to unit test this, I learnt that creating a file mock using a Mocking framework is not a good practice . What do I test here? The only way of testing this is to probably do the file write again, and check if the expected contents and actual contents are the same. In that case, doing it the JUnit way would be as mentioned in this post How to test write to file in Java?. However, I am not going to rewrite the file writing code, to include interface wrappers. How do I go about with this?

@Test public void testfileWrite() {
  String msg = "somemessage";
  String fpath = "path/to/file";
  Writer file_writer = new OutputStreamWriter(new FileOutputStream(fpath), "UTF8");
  file_writer.write(msg);
  assertEquals("somemessage", file_writer.toString()); 
}

Is this all that needs to be tested?

Community
  • 1
  • 1
Tania
  • 1,855
  • 1
  • 15
  • 38

3 Answers3

6

The point of this class is to write a file. It does nothing else (and that is a good thing). So don't bother with a mockist unit test, all it shows is that you can write a ton of mock code. Instead write a Integration Test.

Use the JUnit rule TemporaryFolder to create and destroy a folder to put your test file in, then verify the file has what you want in it at the end of the test. The only time you should consider mocking for this kind of test is if the exceptional case does something funky. Then you can either do some evil black magic involving Powermock or pass in some form of "File Stream factory". Or ask yourself if that is really such a great place for complex logic that needs testing, and then move it.

When testing classes that make use of WriteToFile, mock or stub WriteToFile.

Michael Lloyd Lee mlk
  • 14,561
  • 3
  • 44
  • 81
1

When it comes to write unit tests that must check generated files, I always prepare myself a repository of cases: For each case, an input file (if necessary), and and a set of expected output files.

I write one test method for each case, where I call the business logic, which will generate one (or some) file into the working directory, and I eventually check if the generated file is equal to the proper expected file.

I prepare the expected files manually and check them in into the Source Control System, so that they belong to each released version. If, in future, the business logic must change its behaviour, then it is required that the expected file be changed accordingly, and that both the code and the file be checked in and tagged together in the same release.

That is the easiest and safest way I found for checking generated files.

Little Santi
  • 8,563
  • 2
  • 18
  • 46
0

Use Powermockito to mock the call to the constructor of FileOutputStream and OutputStreamWriter as in: http://benkiefer.com/blog/2013/04/23/powermockito-constructor-mocking/

Then verify that file_writer methods write(String) and flush() have been invoked twice and once, respectively; and at the end close().

Boris Pavlović
  • 63,078
  • 28
  • 122
  • 148