Как протестировать класс с приватными методами, полями или внутренними классами?
Как мне протестировать класс с использованием JUnit, если у него есть внутренние приватные методы, поля или вложенные классы? Похоже, что изменять модификатор доступа для метода только ради того, чтобы запустить тест, не совсем правильно.
5 ответ(ов)
Лучший способ протестировать приватный метод — это использовать другой публичный метод. Если это невозможно, то, скорее всего, выполняется одно из следующих условий:
- Приватный метод является «мертвой» частью кода.
- В классе, который вы тестируете, присутствует проблема с дизайном.
- Метод, который вы пытаетесь протестировать, не должен быть приватным.
Когда у меня есть приватные методы в классе, которые достаточно сложны, и я чувствую необходимость тестировать их напрямую, это наводит на мысль, что мой класс слишком сложен.
Мой обычный подход к решению таких проблем заключается в том, чтобы выделить новый класс, который будет содержать более "интересные" части. Часто данный метод и поля, с которыми он взаимодействует, а также, возможно, еще один-два метода могут быть извлечены в новый класс.
Новый класс открывает эти методы как "публичные", чтобы они были доступны для юнит-тестирования. Теперь новый и старый классы оба проще, чем оригинальный, что отличает для меня (я стараюсь держать все просто, иначе теряю нить!).
Обратите внимание, что я не предлагаю людям создавать классы без должного обоснования! Основная идея заключается в том, чтобы использовать принципы юнит-тестирования, чтобы помочь вам найти хорошие новые классы.
В общем, юнит-тест предназначен для проверки публичного интерфейса класса или модуля. Поэтому приватные методы являются частью реализации, и их тестирование не ожидается и не требуется.
Вот перевод на русский в стиле ответа на вопрос на StackOverflow.com:
Приведу два примера, когда мне нужно протестировать приватный метод:
Рутины расшифровки - Я не хотел бы делать их доступными для всех просто ради тестирования, иначе любой сможет использовать их для расшифровки. Но эти методы являются важной частью кода, они сложные и должны всегда работать (очевидным исключением является рефлексия, которая может быть использована для просмотра даже приватных методов, если
SecurityManager
не настроен на предотвращение этого).Создание SDK для использования сообществом. Здесь публичность получает совершенно иное значение, поскольку это код, который может увидеть весь мир (а не только внутренние пользователи моего приложения). Я помещаю код в приватные методы, если не хочу, чтобы пользователи SDK его видели — я не считаю это "запахом кода", а просто особенностью программирования SDK. Тем не менее, мне по-прежнему необходимо тестировать мои приватные методы, так как именно в них и находится функциональность моего SDK.
Я понимаю идею тестирования лишь "контракта". Но не вижу смысла настаивать на том, что нельзя тестировать код — тут каждая ситуация уникальна.
Таким образом, мой компромисс заключается в усложнении тестов JUnit с использованием рефлексии, вместо того чтобы компрометировать свою безопасность и SDK.
Приватные методы вызываются публичными методами, поэтому входные данные для ваших публичных методов должны также тестировать приватные методы, которые вызываются этими публичными методами. Если публичный метод не проходит тест, это может указывать на наличие ошибки в приватном методе.
Как проверить, что конкретный метод не был вызван, используя Mockito?
Как проверить, что в JUnit-тестах выбрасывается определенное исключение?
Как замокировать методы с возвращаемым типом void с помощью Mockito
Как установить Java 8 на Mac
Что значит 'synchronized'?