Mockito和BufferedReader

时间:2017-08-23 12:01:38

标签: java unit-testing testing mockito

我正在尝试测试一个进行文件/流处理的类。例如,方法readFile将使用BufferedReader返回ArrayList字符串,其中包含文件的每一行:

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;
    }

但是当我使用Mockito来模拟bufferedReader方法“readLine()”时,由于FileNotFoundException构造函数而抛出FileReader。我必须使用temporaryFile或模拟FileReader构造函数吗?

@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"));
}

谢谢

2 个答案:

答案 0 :(得分:3)

readFile BufferedReader换行FileReaderFileReader 内创建该方法,这样您就没有机会模仿FileReader这意味着您无法模拟BufferedReader实例中的输入。

这种方法使测试变得困难。

我建议改变你的做法。例如:

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

然后你的测试可能是:

@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));
}

或者根本没有Mockito:

@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));
}

另一种方法是创建一个实际的文件并读取它,即不需要嘲笑任何东西。您可以使用JUnit的Temporary Folder Rule来帮助在测试后进行清理。

另请注意:readFile()未安全关闭BufferedReaderFileReader

答案 1 :(得分:1)

由于FileUtil确实读取了name引用的文件,因此您需要在文件系统中创建一个文件。

很容易做到这一点
File tempFile = File.createTempFile("temp", ".tmp");
tempFile.deleteOnExit(true);

关于实施代码的一些话:

ArrayList<String> result = new ArrayList<String>();
// combine directory and file name like this
File f = new File(STORAGE_DIRECTORY, fileName);
// use try-with-resource here, like this:
try (BufferedReader br = new BufferedReader(new FileReader(f)))  {

    String sCurrentLine;

    while ((sCurrentLine = br.readLine()) != null) {
        result.add(sCurrentLine);
    }
    } catch (FileNotFoundException e) {
        // no need to create a new list
        return Collections.emptyList()
    } catch (IOException e) {
        return Collections.emptyList()
    }

    // you don't need to close the reader if you use try-with-resource

    return result;
}

您当然可以使用Files#readAllLines。

try {
    return Files.readAllLines(Paths.get(STORAGE_DIRECTORY, fileName), StandardCharsets.UTF-8);
} catch (IOException e) {
    return Collections.emptyList();
}