«1. Обзор

При модульном тестировании нам иногда может понадобиться проверить сообщения, которые мы пишем в стандартный вывод через System.out.println().

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

В этом кратком руководстве мы рассмотрим несколько способов модульного тестирования System.out.println() с помощью JUnit.

2. Простой метод печати

На протяжении всего этого руководства в центре внимания наших тестов будет простой метод, который записывает в стандартный поток вывода: статический окончательный объект PrintStream, представляющий стандартный поток вывода, предназначенный для общесистемного использования.

private void print(String output) {
    System.out.println(output);
}

3. Работа с Core Java

Теперь давайте посмотрим, как мы можем написать модульный тест для проверки содержимого того, что мы отправляем методу println. Однако, прежде чем мы напишем наш фактический модульный тест, нам нужно обеспечить некоторую инициализацию в нашем тесте:

В методе setUp мы переназначаем стандартный поток вывода новому PrintStream с ByteArrayOutputStream. Как мы увидим, в этом потоке вывода теперь будут печататься значения:

private final PrintStream standardOut = System.out;
private final ByteArrayOutputStream outputStreamCaptor = new ByteArrayOutputStream();

@BeforeEach
public void setUp() {
    System.setOut(new PrintStream(outputStreamCaptor));
}

После того, как мы вызвали метод печати с выбранным текстом, мы можем убедиться, что outputStreamCaptor содержит ожидаемое содержимое. Мы вызываем метод trim, чтобы удалить новую строку, которую добавляет System.out.println().

@Test
void givenSystemOutRedirection_whenInvokePrintln_thenOutputCaptorSuccess() {
    print("Hello Baeldung Readers!!");
        
    Assert.assertEquals("Hello Baeldung Readers!!", outputStreamCaptor.toString()
      .trim());
}

Поскольку стандартный поток вывода является общим статическим ресурсом, используемым другими частями системы, мы должны позаботиться о его восстановлении до исходного состояния после завершения нашего теста:

Это гарантирует, что мы не получим любые нежелательные побочные эффекты позже в других тестах.

@AfterEach
public void tearDown() {
    System.setOut(standardOut);
}

4. Использование системных правил

В этом разделе мы рассмотрим удобную внешнюю библиотеку под названием System Rules, которая предоставляет набор правил JUnit для тестирования кода, использующего класс System.

Давайте начнем с добавления зависимости в наш pom.xml:

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

<dependency>
    <groupId>com.github.stefanbirkner</groupId>
    <artifactId>system-rules</artifactId>
    <version>1.19.0</version>
    <scope>test</scope>
</dependency>

Довольно круто! Используя SystemOutRule, мы можем перехватывать записи в System.out. Во-первых, мы начинаем регистрировать все, что пишется в System.out, вызывая метод enableLog в нашем правиле. Затем мы просто вызываем getLog, чтобы получить текст, записанный в System.out, так как мы вызвали enableLog.

@Rule
public final SystemOutRule systemOutRule = new SystemOutRule().enableLog();

@Test
public void givenSystemOutRule_whenInvokePrintln_thenLogSuccess() {
    print("Hello Baeldung Readers!!");

    Assert.assertEquals("Hello Baeldung Readers!!", systemOutRule.getLog()
      .trim());
}

Это правило также включает удобный метод, который возвращает журнал, который всегда имеет разделитель строк \\n

5. Использование системных правил с JUnit5 и Lambdas

Assert.assertEquals("Hello Baeldung Readers!!\n", systemOutRule.getLogWithNormalizedLineSeparator());

В JUnit5 модель правил была заменена на расширения. К счастью, библиотека системных правил, представленная в предыдущем разделе, имеет вариант, подготовленный для работы с JUnit5.

System Lambda доступна в Maven Central. Итак, мы можем продолжить и добавить его в наш pom.xml:

Теперь давайте реализуем наш тест, используя эту версию библиотеки:

<dependency>
    <groupId>com.github.stefanbirkner</groupId>
    <artifactId>system-lambda</artifactId>
    <version>1.0.0</version>
    <scope>test</scope>
</dependency>

В этой версии мы используем метод tapSystemOut, который выполняет оператор и позволяет нам захватить содержимое, переданное в System.out.

@Test
void givenTapSystemOut_whenInvokePrintln_thenOutputIsReturnedSuccessfully() throws Exception {

    String text = tapSystemOut(() -> {
        print("Hello Baeldung Readers!!");
    });

    Assert.assertEquals("Hello Baeldung Readers!!", text.trim());
}

6. Заключение

В этом уроке мы узнали о нескольких подходах к тестированию System.out.println. В первом подходе мы увидели, как перенаправить туда, где мы записываем стандартный поток вывода, используя ядро ​​Java.

Затем мы увидели, как использовать многообещающую внешнюю библиотеку под названием System Rules, используя сначала правила стиля JUnit 4, а затем работая с лямбда-выражениями.

Как всегда, полный исходный код статьи доступен на GitHub.

«