Рубрики
Без рубрики

Насмешливые Статические Методы С Помощью Mockito

Автор оригинала: Jonathan Cook.

1. Обзор

Чаще всего при написании модульных тестов мы сталкиваемся с ситуацией, когда нам нужно имитировать статический метод. До версии 3.4.0 Mockito было невозможно напрямую имитировать статические методы – только с помощью PowerMockito .

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

2. Простой Статический Служебный Класс

На протяжении всего этого урока в центре внимания наших тестов будет простой статический служебный класс:

public class StaticUtils {

    private StaticUtils() {}

    public static List range(int start, int end) {
        return IntStream.range(start, end)
          .boxed()
          .collect(Collectors.toList());
    }

    public static String name() {
        return "Baeldung";
    }
}

Для демонстрационных целей у нас есть один метод с некоторыми аргументами и другой, который просто возвращает строку /.

3. Зависимости

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


    org.mockito
    mockito-inline
    3.8.0
    test

Стоит отметить, что в какой-то момент , согласно документации , эта функциональность вполне может быть интегрирована в более знакомую mockito-core зависимость.

4. Краткое слово о тестировании статических методов

Вообще говоря, некоторые могут сказать, что при написании чистого объектно-ориентированного кода нам не нужно издеваться над статическими классами. Обычно это может указывать на проблему с дизайном или запах кода в нашем приложении.

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

Поэтому всегда стоит исследовать, можем ли мы рефакторировать наш код, чтобы сделать его более тестируемым . Конечно, это не всегда возможно, и иногда мы вынуждены издеваться над статическими методами.

5. Насмешка над статическим методом Без аргументов

Давайте продолжим и посмотрим, как мы можем издеваться над методом name из нашего класса StaticUtils :

@Test
void givenStaticMethodWithNoArgs_whenMocked_thenReturnsMockSuccessfully() {
    assertThat(StaticUtils.name()).isEqualTo("Baeldung");

    try (MockedStatic utilities = Mockito.mockStatic(StaticUtils.class)) {
        utilities.when(StaticUtils::name).thenReturn("Eugen");
        assertThat(StaticUtils.name()).isEqualTo("Eugen");
    }

    assertThat(StaticUtils.name()).isEqualTo("Baeldung");
}

Как уже упоминалось ранее, начиная с Mockito 3.4.0, мы можем использовать метод Mockito.mock Static( Class Classstomock ) для имитационных вызовов статических методов. Этот метод возвращает Издевательский статический объект для нашего типа, который является поддельным объектом с областью действия.

Поэтому в нашем модульном тесте выше переменная utilities представляет собой макет с явной областью видимости threadlocal. Важно отметить, что макеты с областью действия должны быть закрыты сущностью, которая активирует макет . Вот почему мы определяем наш макет в конструкции try-with-resources , чтобы макет автоматически закрывался, когда мы закончим с нашим блоком области действия.

Это особенно приятная функция, поскольку она гарантирует, что наш статический макет остается временным. Как мы знаем, если мы играем со статическими вызовами методов во время наших тестовых запусков, это, скорее всего, приведет к неблагоприятным последствиям в результатах наших тестов из-за параллельного и последовательного характера выполняемых тестов.

Кроме того, еще одним приятным побочным эффектом является то, что наши тесты по-прежнему будут выполняться очень быстро, поскольку Mockito не нужно заменять загрузчик классов для каждого теста.

В нашем примере мы повторяем этот момент, проверяя до и после нашего блока области действия, что наш статический метод name возвращает реальное значение.

6. Издевательство Над Статическим Методом С Аргументами

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

@Test
void givenStaticMethodWithArgs_whenMocked_thenReturnsMockSuccessfully() {
    assertThat(StaticUtils.range(2, 6)).containsExactly(2, 3, 4, 5);

    try (MockedStatic utilities = Mockito.mockStatic(StaticUtils.class)) {
        utilities.when(() -> StaticUtils.range(2, 6))
          .thenReturn(Arrays.asList(10, 11, 12));

        assertThat(StaticUtils.range(2, 6)).containsExactly(10, 11, 12);
    }

    assertThat(StaticUtils.range(2, 6)).containsExactly(2, 3, 4, 5);
}

Как мы видим, мы следуем тому же подходу, что и ранее, за исключением того, что на этот раз мы используем лямбда-выражение внутри нашего предложения when , где мы указываем метод вместе с любыми аргументами, которые мы хотим высмеять . Довольно просто!

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

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

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