4

how can I write a JUnit test, that checks if a FileInputStream has been closed?

Consider the following code,

import java.io.FileInputStream;

class FileInputStreamDemo {

  public static void main(String args[]) throws Exception {
    FileInputStream fis = new FileInputStream(args[0]);

    // Read and display data
    int i;
    while ((i = fis.read()) != -1) {
      System.out.println(i);
    }

    fis.close();

  }
}

I would like to write a test like this:

@Test
public void test() {
  FileInputStreamDemo.main("file.txt");
  // test here, if input stream to file is closed correctly
}

Although this code example doesn't make much sense, I would like to now how to write a JUnit test that checks if the FIS has been closed. (If possible: without even having a reference to the original FIS object)

Bertram Nudelbach
  • 1,783
  • 2
  • 15
  • 27

1 Answers1

4

You should create a separate class called MyFileReader which does the job of reading the file. You then create a class MyFileReaderTest which instantiates your new class and calls the methods in it to test that it behaves correctly. If you make fis a protected member of the MyFileReader class the test can access fis and verify it has been closed.

Instead of using FileInputStream you should use an interface like InputStream so that you can create a MockInputStream which doesn't really create a file but keeps track of whether close() was called on it. Then you can test for that in your test code.

Sarel Botha
  • 12,419
  • 7
  • 54
  • 59
  • Indeed that's a nice solution. How would you do it, if the method of interest creates two FIS from two file names. How to test, if the first FIS is correctly closed, when the second throws an exception on creation? – Bertram Nudelbach Jul 11 '12 at 19:48
  • Firstly your MockInputStream needs the ability to sometimes throw an exception. You control it from the test and set an attribute in it that makes it throw an exception. You can use a static variable in the mock object to tell it to throw an exception when it tries to be instantiated. The better way is to use a factory which you can do the same thing with. Then you can change out the factory in the test for your mock factory that always throws an exception. – Sarel Botha Jul 11 '12 at 21:28