«1. Обзор

Некоторые популярные библиотеки макетов, такие как Mockito и Easymock, генерируют макеты, используя преимущества модели классов, основанной на наследовании Java. EasyMock реализует интерфейс во время выполнения, тогда как Mockito наследует от целевого класса для создания имитирующей заглушки.

Ни один из подходов не подходит для статических методов, поскольку статические методы связаны с классом и не могут быть переопределены. Тем не менее, JMockit предоставляет функции имитации статического метода.

В этом уроке мы рассмотрим некоторые из этих функций.

Для ознакомления с JMockit см. нашу предыдущую статью.

2. Зависимости Maven

Начнем с зависимостей Maven:

<dependency>
    <groupId>org.jmockit</groupId>
    <artifactId>jmockit</artifactId>
    <version>1.24</version>
    <scope>test</scope>
</dependency>

Последние версии этих библиотек можно найти на Maven Central.

3. Статический метод, вызываемый из нестатического метода

Во-первых, давайте рассмотрим случай, когда у нас есть класс с нестатическим методом, который внутренне зависит от статического метода:

public class AppManager {

    public boolean managerResponse(String question) {
        return AppManager.isResponsePositive(question);
    }

    public static boolean isResponsePositive(String value) {
        if (value == null) {
            return false;
        }
        int length = value.length();
        int randomNumber = randomNumber();
        return length == randomNumber ? true : false;
    }

    private static int randomNumber() {
        return new Random().nextInt(7);
    }
}

Теперь мы хотим для проверки метода managerResponse(). Поскольку его возвращаемое значение зависит от другого метода, нам нужно имитировать метод isResponsePositive().

Мы можем имитировать этот статический метод, используя анонимный класс JMockit mockit.MockUp.MockUp\u003cT\u003e (где T будет именем класса) и аннотацию @Mock:

@Test
public void givenAppManager_whenStaticMethodCalled_thenValidateExpectedResponse() {
    new MockUp<AppManager>() {
        @Mock
        public boolean isResponsePositive(String value) {
            return false;
        }
    };

    assertFalse(appManager.managerResponse("Some string..."));
}

Здесь мы имитируем isResponsePositive() с возвращаемым значением, которое мы хотели бы использовать для теста. Поэтому проверка ожидаемого результата с помощью утилиты Assertions, доступной в Junit-5.

4. Тестирование закрытого статического метода

В некоторых случаях другие методы используют закрытые статические методы класса:

private static Integer stringToInteger(String num) {
    return Integer.parseInt(num);
}

Для тестирования такого метода нам нужно имитировать закрытый статический метод. Мы можем использовать служебный метод Deencapsulation.invoke(), предоставляемый JMockit:

@Test
public void givenAppManager_whenPrivateStaticMethod_thenValidateExpectedResponse() {
    int response = Deencapsulation.invoke(AppManager.class, "stringToInteger", "110");
    assertEquals(110, response);
}

Как следует из названия, его цель — деинкапсулировать состояние объекта. Таким образом, JMockit упрощает методы тестирования, которые иначе было бы невозможно протестировать.

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

В этой статье мы увидели, как можно имитировать статические методы с помощью JMockit. Чтобы более подробно ознакомиться с некоторыми расширенными функциями JMockit, ознакомьтесь с нашей статьей о расширенном использовании JMockit.

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