How to unit test a method that reads a given file

2019-02-12 23:10发布

问题:

I know this is a bit naive. How to unit test this piece of code without giving physical file as input. I am new to mockito and unit testing. So I am not sure. Please help.

public static String fileToString(File file) throws IOException
{
    BufferedReader br = new BufferedReader(new FileReader(file));
    try {
        StringBuilder sb = new StringBuilder();
        String line = br.readLine();

        while (line != null) {
            sb.append(line);
            sb.append("\n");
            line = br.readLine();
        }
        return sb.toString();
    } finally {
        br.close();
    }
}

回答1:

You should probably refactor your method. As you realized, a method taking a file as input isn't easily testable. Also, it seems to be static, which doesn't help testability. If you rewrite your method as :

public String fileToString(BufferedReader input) throws IOException

it will be much easier to test. You separate your business logic form the technicalities of reading a file. As I understand it, your business logic is reading a stream and ensuring the line endings are unix style.

If you do that, your method will be testable. You also make it more generic : it can now read from a file, from a URL, or from any kind of stream. Better code, easier to test ...



回答2:

You can create a file as part of the test, no need to mock it out.

JUnit does have a nice functionality for creating files used for testing and automatically cleaning them up using the TemporaryFolder rule.

public class MyTestClass {

    @Rule
    public TemporaryFolder folder = new TemporaryFolder();

    @Test
    public void myTest() {
        // this folder gets cleaned up automatically by JUnit
        File file = folder.newFile("someTestFile.txt");

        // populate the file
        // run your test
    }
}


回答3:

Why do you wanna mock a file? Mocking java.io.File is a bad idea as it has loads of native stuff. I would advice you to ensure that a minimalist text file is available in classpath when the unit tests are run. You can convert this file to text and confirm the output.



回答4:

you could use combination of ByteArrayInputStream and BufferedReader class, to make your required file within your code. So there wouldn't be any need to create a real File on your system. What would happen if you don't have enough permission --based of some specific circumstances -- to create a file. On the code below, you create your own desirable content of your file:

public static void main(String a[]){

    String str = "converting to input stream"+
                    "\n and this is second line";
    byte[] content = str.getBytes();
    InputStream is = null;
    BufferedReader bfReader = null;
    try {
        is = new ByteArrayInputStream(content);
        bfReader = new BufferedReader(new InputStreamReader(is));
        String temp = null;
        while((temp = bfReader.readLine()) != null){
            System.out.println(temp);
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try{
            if(is != null) is.close();
        } catch (Exception ex){

        }
    }

}