0

What's the best approach to writing a unit test for a method that reads a file.

Should I be mocking the file like this?

File dumpFile = Mockito.mock(File.class);
Mockito.when(getDumpAsFile()).thenReturn(dumpFile);

Method Under Test

public List<String> getDumpAsList() {
  CSVReader reader = null;
  List<String> errors = new ArrayList<>();

  try {
    File f = getDumpAsFile();
    reader = new CSVReader(f, "UTF-8");
    reader.setLinesToSkip(0);
    reader.setFieldSeparator(new char[] {','});
    reader.setTextSeparator('"');

    while(reader.readNextLine()) {
      String line = reader.getSourceLine();
      if (line != null && isErrorLine(line)) {
        errors.add(line);
      }
    }

  } catch (FileNotFoundException e) {

  } catch (Exception e) {
    throw new RuntimeException("Cannot extract dumped items", e);

  } finally {
    if (reader != null) {
      reader.closeQuietly();
    }
  }

  return errors;
}       
A_B
  • 1,009
  • 3
  • 15
  • 37
  • 1
    There's little value in a mock here. You should at a minimum return an actual test file to parse. – Makoto Dec 19 '17 at 17:02
  • 2
    Instead of returning a File from getDumpAsFile(), return an InputStream. That way, you can mock this method and make it return a ByteArrayInputStream, reading from a hard-coded byte array in your test. – JB Nizet Dec 19 '17 at 17:07
  • Marking as a dupe of [this older question](https://stackoverflow.com/q/17681708/1426891), which is about mocking `File` with Mockito (i.e. don't) and what to do instead. In short, you can split it so the heavy unit testing happens to higher-level abstractions like InputStream or Reader, and integration testing can happen as in _glytching_'s answer below. Let me know if that Q&A doesn't solve your problem equivalently. – Jeff Bowman Dec 19 '17 at 18:41
  • you need an actual test file, or this test is useless – Oliver Watkins Jun 12 '18 at 10:36

1 Answers1

0

You could use JUnit's TemporaryFolder rule (or, if using JUnit5, its equivalent extension) to create an input file for your test(s).

You would then let getDumpAsFile() return this file and your test would operate on the file you created. On completion of the test JUnit will discard the temporary folder, thereby adhering to the test principle of self containment.

This is, I think, the approach which most closely mirrors the actual behaviour of the getDumpAsList method.

glytching
  • 44,936
  • 9
  • 114
  • 120