Тестирование методов с System.exit() в JUnit: решения

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Java
Скопировать код
// С помощью правила ExpectedSystemExit из JUnit вы можете перехватить вызов System.exit.
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.ExpectedSystemExit;

public class GhostProgrammer {
    @Rule
    public final ExpectedSystemExit exit = ExpectedSystemExit.none();

    @Test
    public void actuallyExits() {
        exit.expectSystemExit();
        System.exit(42); // Возможно, мы нашли ответ на вопрос о смысле жизни, вселенной и всего такого!
    }
}

С помощью этого подхода вы перехватываете системный вызов выхода и предотвращаете завершение работы JVM во время тестирования!

Кинга Идем в IT: пошаговый план для смены профессии

Альтернативы вызову выхода

Если использование ExpectedSystemExit не подходит для вас столько же, сколько и ананас на пицце, мы предлагаем другие варианты:

Агрессивный пацифист: неуправляемые исключения

Java
Скопировать код
    public void gracefulShutdown(int status) {
        throw new RuntimeException("Розы красные, моя любовь к тестам бездонна, завершаем с кодом " + status);
    }

JVM не завершает работу, но изящество ситуации нарушается через обработку исключений.

Превентивный родитель: Собственный SecurityManager

Java
Скопировать код
    public class ConservativeSecurityManager extends SecurityManager {
        @Override
        public void checkExit(int status) {
            super.checkExit(status);
            throw new SecurityException("Куда собрались, молодой человек?!");
        }
    }

Это подобно запрету на опоздания после комендантского часа! SecurityException: вы попались!

Шепчущий за кулисами: System Lambda

Java
Скопировать код
import static com.github.stefanbirkner.systemlambda.SystemLambda.catchSystemExit;
public class SneakyCode {
    @Test
    public void exitsLikeANinja() {
        int status = catchSystemExit(() -> {
            System.exit(0); // Как ниндзя, не оставляющий за собой следов.
        });
        assertEquals(0, status); // Следы остыли.
    }
}

System Lambda — это библиотека для любителей тестирования, предпочитающих использовать Java 8+.

Визуализация

// мой код не работает? Возможно, проблема во мне самом.

Markdown
Скопировать код
Основная идея тестирования такова: 
Вместо того чтобы позволить коду исчезнуть, словно испариться через дверь с надписью EXIT 🚪💨, 
вы говорите ему: "Беги, функция, беги!" 🏃💨, но затем можете остановить его посреди пути 🛑✋

Способы перехвата:
1. Борьба за голосование: замените стандартный `SecurityManager` своим [🛡]
("Тимми, нельзя выходить, пока ты не съешь брокколи!")
2. Будучи маршалом: используйте библиотеку `System Rules` для установки правил [📜➡️🔏]
3. Невидимый страж: ожидайте вызова 'exit' с помощью `ExpectedException` от JUnit [👀🚨]

Продвинутые стратегии

Выполнение вышеуказанных инструкций, вероятно, поможет решить вашу проблему с методами, вызывающими "system-exit". Однако, если ваша задача кажется ещё более сложной, рассмотрите следующие опции:

Java 21+: Новый порядок

В эпоху Java 21 вводится новый параметр -Djava.security.manager=allow. Убедитесь, что он установлен правильно!

Изменения глобального состояния: Корректируем эффект бабочки

Если вы изменили глобальное состояние (например, статическую переменную), исправьте это, откатив эти изменения перед тестированием и после его завершения.

Инструменты покрытия: Шпион, которого я люблю

Инструменты, такие как EclEmma, разработаны для анализа покрытия кода тестами и требуют корректного завершения программы для точного отчета. Проверьте их совместимость.

Непрерывная интеграция: Великое представление

На этапе CI-пайплайна, неожиданный вызов System.exit() может прекратить исполнение сценария! Учтите перечисленные стратегии, чтобы шоу продолжилось.

Полезные материалы

  1. java – Как тестировать методы, которые вызывают System.exit()? Обсуждение на Stack Overflow о лучших способах тестирования System.exit().
  2. System Rules Библиотека, прямая и по существу. Рекомендуется к ознакомлению.
  3. SecurityManager (Java Platform SE 8 ) Официальная документация от Oracle. Нет, System.exit() не был создан, чтобы запутать вас.
  4. Пользовательское руководство JUnit 5 Когда ваши тесты отказываются смотреть на вещи вашими глазами.
  5. GitHub – powermock/powermock: PowerMock – Java-фреймворк, который позволяет тестировать код, который обычно не тестируют. Мощный фреймворк для создания моков. Постарайтесь уделить ему внимание.
  6. Lang – Home Это не просто библиотека Apache. Она действительно необычайна!
  7. Стоит ли мгновения... Несмотря на свою краткость, этот материал может быть очень полезным для ваших тестов в долгосрочной перспективе.