Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Good practice with Mockito And BufferedReader

I'm trying to test a class that makes File/Stream treatment. For instance, the method readFile will use BufferedReader to return an ArrayList of String with every lines of the file inside:

public ArrayList<String> readFile(String fileName)
{
    ArrayList<String> result = new ArrayList<String>();
    FileReader fr = null;
    BufferedReader br = null;
    try {

        fr = new FileReader(STORAGE_DIRECTORY+fileName);
        br = new BufferedReader(fr);
        String sCurrentLine;

        while ((sCurrentLine = br.readLine()) != null) {
            result.add(sCurrentLine);
        }
    }
        catch (FileNotFoundException e) {


            return new ArrayList<String>();
        } catch (IOException e) {

            return new ArrayList<String>();
        }

        br.close();
        fr.close();


        return result;
    }

But when I use Mockito in order to mock bufferedReader method "readLine()",a FileNotFoundException is thrown because of FileReader constructor. Must I use temporaryFile or Mock FileReader constructor ?

@Test
public void readFileTest5() throws Exception {
    BufferedReader bufferedReader = Mockito.mock(BufferedReader.class);
    FileReader fileReader = Mockito.mock(FileReader.class);
    when(BufferedReader.readLine()).thenReturn("abc");
    assertEquals("",new ArrayList<String>(), FileUtil.readFile("abc"));
}

Thank you

like image 941
Nicogo Avatar asked Feb 10 '26 10:02

Nicogo


1 Answers

In readFile BufferedReader wraps FileReader and FileReader is created inside that method so you have no opportunity to mock FileReader which means that you have no way to mock the inputs into your BufferedReader instance.

This approach makes testing difficult.

I'd suggest changing your approach. For example:

public ArrayList<String> readFile(BufferedReader reader) {
    // ...
}

Then your test could be:

@Test
public void readFileTest() throws Exception {
    BufferedReader bufferedReader = Mockito.mock(BufferedReader.class);
    Mockito.when(bufferedReader.readLine()).thenReturn("a", "b", "c", null);
    List<String> expected = Arrays.asList("a", "b", "c");
    Assert.assertEquals("", expected, readFile(bufferedReader));
}

Or without Mockito at all:

@Test
public void readFileTest() throws Exception {
    BufferedReader bufferedReader = new BufferedReader(new StringReader("a\nb\nc"));
    List<String> expected = Arrays.asList("a", "b", "c");
    Assert.assertEquals("", expected, readFile(bufferedReader));
}

Another approach would be to create an actual file and read it i.e. no need for mocking anything. You could use JUnit's Temporary Folder Rule to help clean up after the test.

On a separate note: the readFile() isn't closing the BufferedReader and FileReader safely.

like image 128
glytching Avatar answered Feb 13 '26 04:02

glytching



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!