Мокування статичного методу mockStatic()

Ще один важливий момент – мокування та верифікація статичних методів. "А що в цьому такого?", запитаєш ти. Так, статичні, але ж методи. Але це не так.

Пам'ятаєш з чого ми почали вивчення мок-об'єктів? З того, що ці об'єкти штучно створюються через клас DynamicProxy. Статичні методи до жодних об'єктів не прив'язані, і перехопити виклики до них через DynamicProxy не можна. От і все.

Але творці Mockito і тут змогли викрутитись – написали свій завантажувач класів і з його допомогою отримали змогу підміняти класи на льоту. Велика і складна робота, але вони таки змогли це зробити.

Потрібно додати ще одну бібліотеку до pom.xml:

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-inline</artifactId>
    <version>4.2.0</version>
    <scope>test</scope>
</dependency>

Ось як потрібно працювати, якщо тобі потрібно мокувати статичний метод.

1. Створюємо спеціальний мок-об'єкт класу:

MockedStatic<Ім'яКласа>керуючийОб'єкт = Mockito.mockStatic(Ім'яКласу.class);

2. Додаємо до цього об'єкта правила роботи:

До цього об'єкта правила потрібно чіпляти іншими способами.

керуючийОб'єкт.when(Ім'яКласа::ім'яМетоду).thenReturn(результат);

3 Обов'язково загортаємо використання цього об'єкта в try-with-resources, щоб об'єкт одразу видалився, і Mockito могло очистити пов'язані з ним правила.

Приклад:


@Test
void givenStaticMethodWithNoArgs () {
    try (MockedStatic< StaticUtils> utilities =  Mockito.mockStatic( StaticUtils.class)) {
        //додаємо правило
         utilities.when(StaticUtils::name).thenReturn("Привіт");

        //перевіряємо, що правило працює
        assertEquals("Привіт", StaticUtils.name());
    }
}

Не так гарно, як з анотаціями @Mock і @Spy, проте дуже практично. Було дуже важко писати тести, доки не можна було замокати простий статичний метод, який використовувався всередині методів, що тестуються.