1. Обзор
Одной из проблем модульного тестирования является имитация частных методов.
В этом руководстве мы узнаем, как этого добиться с помощью библиотеки PowerMock , которая поддерживается JUnit и TestNG.
PowerMock интегрируется с фреймворками для имитации, такими как EasyMock и Mockito, и предназначен для добавления к ним дополнительных функций, таких как имитация частных методов, конечных классов, конечных методов и т. д.
Он делает это, полагаясь на манипуляции с байт-кодом и совершенно отдельный загрузчик классов.
2. Зависимости Maven
Во-первых, давайте добавим необходимые зависимости для использования PowerMock с Mockito и JUnit в наш pom.xml
:
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>1.7.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>1.7.3</version>
<scope>test</scope>
</dependency>
Последние версии можно посмотреть здесь и здесь .
3. Пример
Давайте начнем с примера LuckyNumberGenerator.
Этот класс имеет единственный общедоступный метод для генерации счастливого числа:
public int getLuckyNumber(String name) {
saveIntoDatabase(name);
if (name == null) {
return getDefaultLuckyNumber();
}
return getComputedLuckyNumber(name.length());
}
4. Вариации насмешек над приватными методами
Для исчерпывающего модульного тестирования метода нам потребуется имитировать частные методы.
4.1. Метод без аргументов, но с возвращаемым значением
В качестве простого примера давайте смоделируем поведение приватного метода без аргументов и заставим его возвращать желаемое значение:
LuckyNumberGenerator mock = spy(new LuckyNumberGenerator());
when(mock, "getDefaultLuckyNumber").thenReturn(300);
В этом случае мы имитируем закрытый метод getDefaultLuckyNumber
и заставляем его возвращать значение 300.
4.2. Метод с аргументом и возвращаемым значением
Далее смоделируем поведение приватного метода с аргументом и заставим его возвращать нужное значение:
LuckyNumberGenerator mock = spy(new LuckyNumberGenerator());
doReturn(1).when(mock, "getComputedLuckyNumber", ArgumentMatchers.anyInt());
В этом случае мы имитируем закрытый метод и заставляем его возвращать 1.
Обратите внимание, что нам не важен входной аргумент, и мы используем ArgumentMatchers.anyInt()
в качестве подстановочного знака.
4.3. Проверка вызова метода
Наша последняя стратегия — использовать PowerMock для проверки вызова закрытого метода:
LuckyNumberGenerator mock = spy(new LuckyNumberGenerator());
int result = mock.getLuckyNumber("Tyranosorous");
verifyPrivate(mock).invoke("saveIntoDatabase", ArgumentMatchers.anyString());
5. Предостережение
Наконец, хотя приватные методы можно тестировать с помощью PowerMock, мы должны быть особенно осторожны при использовании этого метода.
Учитывая, что целью нашего тестирования является проверка поведения класса, мы должны воздерживаться от изменения внутреннего поведения класса во время модульного тестирования.
Методы имитации следует применять к внешним зависимостям класса, а не к самому классу.
Если насмешка над закрытыми методами необходима для тестирования наших классов, это обычно указывает на плохой дизайн.
6. Заключение
В этой быстрой статье мы показали, как PowerMock можно использовать для расширения возможностей Mockito для имитации и проверки частных методов в тестируемом классе.
Исходный код этого руководства можно найти на GitHub .