Search code examples
javafile-iomockingtddmockito

Suggestions on how to test a BufferedReader and FileReader that takes in strings and puts them into an ArrayList


I have a class which has a method that reads a text file line by line and then puts each line into an ArrayList of Strings. Here is my code:

public class ReadFile {

    public List<String> showListOfCourses() throws IOException {
        String filename = "countriesInEurope.txt";
        FileReader fr = new FileReader(filename);
        BufferedReader br = new BufferedReader(fr);
        List<String> courseList = new ArrayList<>();

        while (true) {
            String line = br.readLine();
            if (line == null) {
                break;
            }

            courseList.add(line);
        }
        br.close();

        return courseList;
    }

}

I was hoping for a few suggestions on how to test this method through Mockito involving Arrange/Act/Assert. I have heard readers which involve text files can be tricky to test and that creating a temporary file for is not best practice as it uses up memory? Any suggestions will be really appreciated.


Solution

  • As the filename countriesInEurope.txt is hardcoded in your implementation, this is not testable. A good way to make this testable would be to refactor the method to take a Reader as parameter:

    public List<String> showListOfCourses(Reader reader) throws IOException {
        BufferedReader br = new BufferedReader(reader);
        List<String> courseList = new ArrayList<>();
    
        // ...
    
        return courseList;
    }
    

    Your main implementation could pass a FileReader to this. On the other hand when testing, your test method could pass a StringReader instance, which is easy to create with a sample content as a simple string, no temporary files needed, for example:

    @Test
    public void showListOfCourses_should_read_apple_orange_banana() {
        Reader reader = new StringReader("apple\norange\nbanana");
        assertEquals(Arrays.asList("apple", "orange", "banana"), showListOfCourses(reader));
    }
    

    Btw the name of the method is not good, as it doesn't "show" anything. readListOfCourses would make more sense.