ПРИХОДИТЕ УЧИТЬСЯ НОВОЙ ПРОФЕССИИ ЛЕТОМ СО СКИДКОЙ ДО 70%Забронировать скидку
logo

Мокирование переменных класса в Java с помощью Mockito

Пройдите тест, узнайте какой профессии подходите и получите бесплатную карьерную консультацию
В конце подарим скидку до 55% на обучение
Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Для того чтобы смоделировать объекты, зависимые от тестируемого, используются аннотации @Mock и @InjectMocks, которые предоставляет библиотека Mockito. Mockito автоматически внедряет созданные таким образом "моки" (от английского "mock" – подделка, имитация) в тестируемый объект. Посмотрим, как это работает на примерах:

Java
Скопировать код
public class Spaceship {
    private NavigationSystem navSystem; // Система навигации космического корабля
    // ... функционал корабля, использующий 'navSystem'...
}

public class SpaceshipTest {
    @Mock NavigationSystem mockNavSystem; // Имитация системы навигации
    @InjectMocks Spaceship spaceship; // Объект, в который внедряются "моки"
    // ... тестирование функционала 'spaceship' с имитацией 'mockNavSystem'...
}

Итак, с помощью аннотаций @InjectMocks и @Mock возможно внедрить имитацию mockNavSystem в объект spaceship, что упрощает процесс его тестирования.

Рефакторинг кода: облегчаем тестирование

Для удобства работы с Mockito ваш код должен быть организован так, чтобы внедрение зависимостей осуществлялось максимально просто. Если доступ к полям класса ограничен, можно:

  • Ввести сеттеры для упрощения инъекции "моков".
  • Изменить конструктор так, чтобы зависимости можно было передавать в виде параметров.

Недоступные элементы: использование рефлексии

В тех случаях, когда прямой рефакторинг не является возможным и поля класса недоступны для мокирования, можно использовать ReflectionTestUtils из Spring Framework:

Java
Скопировать код
ReflectionTestUtils.setField(spaceship, "navSystem", mockNavSystem);

Как альтернативу можно разработать вспомогательный класс TestUtils, который будет использовать рефлексию для доступа к приватным полям. Тем не менее, стоит помнить, что излишнее использование рефлексии может сигнализировать о необходимости рефакторинга кода.

Чрезмерное мокирование: зона риска

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

Визуализация

Принцип работы мокирования иллюстрируется на примере робота:

Markdown
Скопировать код
Class: Robot 🤖
Member Variable: Battery 🔋

Без мокирования:
🔋 = RealBattery(); // Реальная батарея может привести к неожиданным результатам тестов!

С Mockito:
🔋 = mock(Battery.class); // 🤖 Имитация батареи, зарядка не требуется!
Markdown
Скопировать код
Реальное тестирование:
🤖🔋[⚙️] -> Результат работы: успешен 📈 либо нет 📉

Тестирование с "моком":
🤖🔋[🔧] -> Результат предсказуем: положительный 👍 либо отрицательный 👎

Вывод: мокирование создаёт контролируемую версию объекта, поддерживающую целостность и предсказуемость в процессе тестирования.

Лучшие практики мокирования: за безопасность и надёжность!

Внедрение зависимостей — не только подход к организации тестирования, но и философия проектирования. Она помогает ориентировать классы на осуществление своих основных функций, минимизируя заботы о создании и обеспечении работы зависимостей.

Шаблоны проектирования: создание структуры

Применение шаблонов проектирования, таких как Фабрика, Стратегия или Локатор Сервисов, делает код более структурированным и его тестирование эффективнее.

Обеспечение правильного использования моков

Mockito предоставляет инструменты для проверки корректности использования моков в тестах:

Java
Скопировать код
verify(mockNavSystem).expectedCourseCorrection(); // Проверка правильности исполнения валидации!

Работа с устаревшим кодом

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

Java
Скопировать код
Field field = Spaceship.class.getDeclaredField("navSystem");
field.setAccessible(true);
field.set(spaceship, mockNavSystem);  // Получен доступ к приватному полю!

Недостатки рефлексии

Использование рефлексии может сделать тесты уязвимыми, поскольку они становятся чувствительными к изменениям в именах и типах полей класса, особенно после проведения рефакторинга.

Полезные материалы

  1. Mockito – Javadoc документация для mockito-core 5.10.0 – обширное описание методов и классов Mockito.
  2. Обучающий видеокурс по использованию Mockito с JUnit и Maven на YouTube — практическое пособие по использованию Mockito.
  3. Обсуждение мокирования приватных полей в Mockito на Stack Overflow — обзор сообщества разработчиков на вопросы мокирования.
  4. Гид по Mockito от Baeldung – уроки и примеры — детальное руководство по использованию Mockito.
  5. Использование Argument Matchers в Mockito – кейсы и примеры — когда и как применять сопоставители аргументов в Mockito.
  6. Аннотации Mockito: @Mock, @Spy, @Captor и @InjectMocks — подробный разбор различных аннотаций Mockito.
  7. Продвинутые приёмы Mockito – решения для сложных задач — мастер-класс по использованию продвинутых функций Mockito.