PowerkMock-In BufferedReader работает промежуточно

То, что я хочу сделать, это высмеивать недавно созданный экземпляр BufferedReader, Вот код, который должен быть проверен:

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 {
        ...
    }
}
...

Что я должен сделать, это PowerMock как FileReader создание и BufferedReader создание.

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

Но тогда тест никогда не заканчивается. Я даже не могу отладить это.

Как только PowerMockito.doAnswer() удаляется код выполняется (и доступен для отладки). Я также пытался использовать Mockito.mock() вместо PowerMockito.doAnswer()это не помогает

Что может стать причиной прерывания выполнения теста?

2 ответа

Решение

Проблема заключалась в том, что мне также пришлось издеваться над ценностью после первого bufferedReader.readLine(), потому что в противном случае он всегда будет возвращать проверенное значение, таким образом, не завершая.

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

НОТА

Хотя это и есть фактический ответ на вопрос, но вы должны строго рассмотреть выбор дизайна, предложенного GhostCat в другом ответе (что я в итоге и сделал).

Просто другая точка зрения: можно сказать, что ваша настоящая проблема в вашем коде - это два вызова new() для FileReader / BufferedReader.

Что делать, если вы передали Reader для этого метода; вместо строки, обозначающей имя файла?

Что если вы передали "ReaderFactory" в базовый класс, содержащий этот метод read(String)? (где вы будете использовать внедрение зависимостей, чтобы получить эту фабрику в свой класс)

Тогда: вы будете искать улучшенный дизайн - и вам не нужно будет использовать PowerMock. Вы можете сделать шаг назад и пойти с Mockito или EasyMock; как не было бы больше необходимости издеваться над вызовами new,

Итак, мой ответ: вы создали сложный для тестирования код. Теперь вы пытаетесь решить проблему дизайна, используя большой (безобразный) молоток PowerMock. Да, это будет работать. Но это всего лишь вторая лучшая альтернатива.

Более разумный вариант - научиться писать тестируемый код (начните здесь, например); и хорошо, напишите тестируемый код. И прекрати использовать PowerMock (я делал это много месяцев назад; после сильной боли, вызванной PowerMock; и я никогда не сожалел об этом решении).

Другие вопросы по тегам