Search code examples
javaunit-testingmockingpowermocktest-double

PowerkMock-ing BufferedReader runs interminately


What I want to do is to mock newly created instance of BufferedReader. Here's the code that should be tested:

A.java

...
@Override
public String read(String fileName) throws IOException {
    ...

    try {
        fileReader = new FileReader(fileName);
        bufferedReader = new BufferedReader(fileReader);
        String tmp;
        StringBuilder builder = new StringBuilder();
        while ((tmp = bufferedReader.readLine()) != null) {
            builder.append(tmp);
        }
        return builder.toString();
    } catch (IOException e) {
        ...
    } finally {
        ...
    }
}
...

What I have to do, is to PowerMock both FileReader creation and BufferedReader creation.

ATest.java

@RunWith(PowerMockRunner.class)
@PrepareForTest(A.class)
public class ATest {

    @Mock
    private FileReader fileReader;
    @Mock
    private BufferedReader bufferedReader;
    ...

    @Test
    public void test() throws Exception {
        PowerMockito.whenNew(FileReader.class).withArguments(FILE_NAME).thenReturn(fileReader);
        PowerMockito.whenNew(BufferedReader.class).withAnyArguments().thenReturn(bufferedReader);
        PowerMockito.doAnswer(new Answer() {
            public Object answer(InvocationOnMock invocation) throws Throwable {
                return "test";
            }
        }).when(bufferedReader).readLine();
        assertArrayEquals(reader.read(FILE_NAME), new String[]{"test"});
    }
}

But then the test never terminates. I can't even debug it.

As soon as PowerMockito.doAnswer() is removed the code is executed (and is available for debugging). I've also tried to use Mockito.mock() instead of PowerMockito.doAnswer(), it doesn't help.

What may cause interminate execution of the test?


Solution

  • The problem was, that I also had to mock value after first bufferedReader.readLine(), because otherwise it would always return the mocked value, thus not terminating.

        Mockito.when(bufferedReader.readLine()).thenReturn("first line").thenReturn(null);
    

    NOTE

    Though this is the actual answer to the question, but you should strongly consider choosing the design GhostCat has suggested in another answer (which I eventually did).