Мне нужно написать тесты JUnit для старого приложения, которое плохо спроектировано и записывает много сообщений об ошибках в стандартный вывод. Когда getResponse(String request)
метод ведет себя правильно, он возвращает ответ XML:
@BeforeClass
public static void setUpClass() throws Exception {
Properties queries = loadPropertiesFile("requests.properties");
Properties responses = loadPropertiesFile("responses.properties");
instance = new ResponseGenerator(queries, responses);
}
@Test
public void testGetResponse() {
String request = "<some>request</some>";
String expResult = "<some>response</some>";
String result = instance.getResponse(request);
assertEquals(expResult, result);
}
Но когда он получает неправильно сформированный XML или не понимает запрос, он возвращает null
и записывает некоторые данные в стандартный вывод.
Есть ли способ утверждать вывод консоли в JUnit? Чтобы ловить такие случаи, как:
System.out.println("match found: " + strExpr);
System.out.println("xml not well formed: " + e.getMessage());
Ответы:
использовать ByteArrayOutputStream и System.setXXX просто:
Примеры тестовых случаев:
Я использовал этот код для проверки опции командной строки (утверждая, что -version выводит строку версии и т. Д. И т. Д.)
Редактировать: предыдущие версии этого ответа называются
System.setOut(null)
после испытаний; Это является причиной обращения к комментаторам NullPointerExceptions.источник
NullPointerException
другими тестами после установки нулевого потока ошибок, как было предложено выше (внутриjava.io.writer(Object)
, вызываемого изнутри валидатором XML). Вместо этого я бы предложил сохранить оригинал в полеoldStdErr = System.err
и восстановить его в@After
методе.Я знаю, что это старая ветка, но для этого есть хорошая библиотека:
Системные правила
Пример из документов:
Это также позволит вам ловить
System.exit(-1)
и другие вещи, для которых инструмент командной строки должен быть проверен.источник
Вместо перенаправления
System.out
я бы реорганизовал класс, который используетSystem.out.println()
, передавPrintStream
в качестве соавтора, а затем используяSystem.out
в производстве и тестового шпиона в тесте. То есть используйте Dependency Injection, чтобы исключить прямое использование стандартного потока вывода.В производстве
В тесте
обсуждение
Таким образом, тестируемый класс становится тестируемым путем простого рефакторинга, без необходимости косвенного перенаправления стандартного вывода или неясного перехвата с системным правилом.
источник
ConsoleWriter
, что испытуемыйВы можете установить поток печати System.out через setOut () (и для
in
иerr
). Можете ли вы перенаправить это в поток печати, который записывает в строку, а затем проверить это? Это будет самый простой механизм.(Я бы посоветовал на каком-то этапе преобразовать приложение в какую-то среду ведения журналов - но я подозреваю, что вы уже знаете об этом!)
источник
Немного не по теме, но в случае, если некоторые люди (например, я, когда я впервые нашел эту тему) могут быть заинтересованы в захвате вывода журнала через SLF4J, JUnit для commons-testing
@Rule
может помочь:Отказ от ответственности :
log4j
,log4j2
иlogback
доступны в данный момент, но я счастлив , чтобы добавить больше.источник
Ответ @dfa хорош, поэтому я сделал еще один шаг, чтобы можно было проверить блоки вывода.
Сначала я создал
TestHelper
с помощью метода,captureOutput
который принимает раздражающий классCaptureTest
. Метод captureOutput выполняет установку и разбор выходных потоков. Когда реализацияCaptureOutput
«Stest
метод вызывается, она имеет доступ к выходу для генерации испытательного блока.Источник для TestHelper:
Обратите внимание, что TestHelper и CaptureTest определены в одном файле.
Затем в своем тесте вы можете импортировать статический captureOutput. Вот пример использования JUnit:
источник
Если вы использовали Spring Boot (вы упомянули, что работаете со старым приложением, так что, вероятно, это не так, но оно может быть полезно для других), то вы можете использовать org.springframework.boot.test.rule.OutputCapture. следующим образом:
источник
Основываясь на ответе @ dfa и другом ответе, который показывает, как тестировать System.in , я хотел бы поделиться своим решением, чтобы дать входную информацию для программы и проверить ее вывод.
В качестве ссылки я использую JUnit 4.12.
Допустим, у нас есть эта программа, которая просто копирует ввод в вывод:
Чтобы проверить это, мы можем использовать следующий класс:
Я не буду много объяснять, потому что я считаю, что код читабелен, и я привел свои источники.
Когда JUnit запускается
testCase1()
, он будет вызывать вспомогательные методы в порядке их появления:setUpOutput()
из-за@Before
аннотацииprovideInput(String data)
позвонил изtestCase1()
getOutput()
позвонил изtestCase1()
restoreSystemInputOutput()
из-за@After
аннотацииЯ не тестировал,
System.err
потому что мне это не нужно, но это должно быть легко реализовать, подобно тестированиюSystem.out
.источник
Вы не хотите перенаправлять поток system.out, потому что он перенаправляет для ВСЕЙ JVM. Все, что работает на JVM, может испортиться. Есть лучшие способы проверить ввод / вывод. Посмотрите на заглушки / издевательства.
источник
Полный пример JUnit 5 для тестирования
System.out
(замените часть когда):источник
Вы не можете напрямую печатать, используя system.out.println или используя logger api при использовании JUnit . Но если вы хотите проверить какие-либо значения, вы можете просто использовать
Будет выдано сообщение об ошибке ниже:
Ваше значение должно быть 21,92. Теперь, если вы будете тестировать, используя это значение, как показано ниже, ваш тестовый пример пройдет.
источник
за
для ошибки
источник
@Rule
вместо того, чтобы делать это встроенным в вашем тесте. Примечательно, что если ваше утверждение не выполнено, второйSystem.setOut/Err
вызов не будет достигнут.