Mockito: чем отличаются Mock и Spy? | OTUS
⚡ Подписка на курсы OTUS!
Интенсивная прокачка навыков для IT-специалистов!
Подробнее

Курсы

Программирование
iOS Developer. Professional Kotlin Backend Developer Flutter Mobile Developer Symfony Framework C++ Developer. Basic Unity Game Developer. Basic Java Developer. Professional
-35%
Highload Architect Unity Game Developer. Professional React.js Developer Специализация Java-разработчик
-25%
Алгоритмы и структуры данных
-16%
Scala-разработчик C# Developer. Professional
-23%
Разработчик голосовых ассистентов и чат-ботов Team Lead Архитектура и шаблоны проектирования NoSQL Web-разработчик на Python Golang Developer. Professional PostgreSQL Vue.js разработчик Супер-практикум по использованию и настройке GIT Разработчик IoT Подготовка к сертификации Oracle Java Programmer (OCAJP) Программист С HTML/CSS
Инфраструктура
Инфраструктурная платформа на основе Kubernetes Microservice Architecture Базы данных Highload Architect Reverse-Engineering. Professional
-8%
Network engineer. Basic Administrator Linux.Basic MongoDB Infrastructure as a code MS SQL Server Developer Cloud Solution Architecture Мониторинг и логирование: Zabbix, Prometheus, ELK Супер-практикум по использованию и настройке GIT Разработчик IoT Экcпресс-курс «ELK» Супер-интенсив "Tarantool" Экспресс-курс «CI/CD или Непрерывная поставка с Docker и Kubernetes» Экспресс-курс «Введение в непрерывную поставку на базе Docker»
Корпоративные курсы
Безопасность веб-приложений Экосистема Hadoop, Spark, Hive Пентест. Практика тестирования на проникновение Node.js Developer Java QA Engineer. Basic
-18%
Reverse-Engineering. Professional
-8%
DevOps практики и инструменты NoSQL Reverse-Engineering. Basic Cloud Solution Architecture Внедрение и работа в DevSecOps Супер-практикум по работе с протоколом BGP Game QA Engineer Супер - интенсив по Kubernetes Дизайн сетей ЦОД Экспресс-курс «IaC Ansible» Экспресс-курс по управлению миграциями (DBVC) Экспресс-курс "Версионирование и командная работа с помощью Git" Основы Windows Server
Специализации Курсы в разработке Подготовительные курсы Подписка
+7 499 938-92-02

Mockito: чем отличаются Mock и Spy?

JavaDeep_5.06_Site.png

Такой вопрос часто можно услышать на собеседовании, когда разговор заходит о unit-тестировании. Mockito позволяет создать объект-заглушку для интерфейса или класса. В случае Mock-объекта, единственное, что будут делать все методы такого объекта, если не определять их поведение, – возвращать значения по-умолчанию: void, default-ы для примитивов, пустые коллекции и null для всех остальных объектов.

Но если какое-то поведение, требуемое для некоторых методов Mock-объекта, нам всё-таки нужно, мы можем его определить.

@RunWith(MockitoJUnitRunner.class)
public class MockTest {

    @Mock
    private Map<Integer, String> map;

    @Test
    public void testMockMapPutDefaultBehavior() {
        //when
        map.put(1, "test");

        //then
        assertThat(map.get(1), is(nullValue()));
    }

    @Test
    public void testMockMapKeySetDefaultBehavior() {
        //when
        map.put(1, "test");

        //then
        assertThat(map.keySet(), is(empty()));
    }

    @Test
    public void testMockMapValuesWithDefinedBehavior() {
        Collection<String> stub = Arrays.asList("test1", "test2", "test3");
        when(map.values()).thenReturn(stub);

        //when
        map.put(1, "test");

        //then
        assertThat(map.values(), is(stub));
    }

}

Помимо этого, Mockito позволяет «шпионить» за реальными объектами. В случае Spy-объекта, по-умолчанию будет исполняться оригинальное поведение методов объекта. Но как и в случае с Mock-объектами, их поведение можно переопределить.

@RunWith(MockitoJUnitRunner.class)
public class SpyTest {

    @Spy
    private Map<Integer, String> map = new HashMap<>();

    @Test
    public void testSpyMapPutDefaultBehavior() {
        //when
        map.put(1, "test");

        //then
        assertThat(map.get(1), is("test"));
    }

    @Test
    public void testSpyMapKeySetDefaultBehavior() {
        //when
        map.put(1, "test1");
        map.put(2, "test2");

        //then
        assertThat(map.keySet(), containsInAnyOrder(1, 2));
    }

    @Test
    public void testSpyMapValuesWithDefinedBehavior() {
        Collection<String> stub = Arrays.asList("test1", "test2", "test3");
        when(map.values()).thenReturn(stub);

        //when
        map.put(1, "test");

        //then
        assertThat(map.values(), is(stub));
    }

}

Если мы хотим протестировать логику самого объекта и при этом не хотим внедрять какие-либо реальные сервисы и компоненты, то в данном случае стоит использовать вместо них Mock-объекты. В случае, если мы хотим протестировать всё вместе, за исключением каких-то специфических случаев, то стоит использовать Spy.

Ссылка на GitHub здесь.

Остались вопросы? Напишите в комментариях!

Не пропустите новые полезные статьи!

Спасибо за подписку!

Мы отправили вам письмо для подтверждения вашего email.
С уважением, OTUS!

Автор
2 комментария
1

Почему примеры кода для Mock и Stub одинаковые?

0

Поправили, спасибо!

Для комментирования необходимо авторизоваться