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

Курсы

Программирование
C++ Developer. Professional JavaScript Developer. Professional Android Developer. Professional Microservice Architecture React.js Developer JavaScript Developer. Basic PostgreSQL Программист С C++ Developer. Basic Team Lead PHP Developer. Professional Подготовка к сертификации Oracle Java Programmer (OCAJP) Алгоритмы и структуры данных Разработчик IoT C# Developer. Basic Unreal Engine Technical Game Design C# ASP.NET Core разработчик Python Developer. Professional Python Developer. Basic Node.js Developer iOS Developer. Professional Cloud Solution Architecture Kotlin Backend Developer Agile Project Manager Scala-разработчик Symfony Framework iOS Developer. Basic Супер-интенсив Azure Специализация Python Developer
Инфраструктура
Экспресс-курс по управлению миграциями (DBVC) Экспресс-курс «IaC Ansible» Microservice Architecture Разработчик программных роботов (RPA) на базе UiPath и PIX Внедрение и работа в DevSecOps NoSQL Специализация Administrator Linux
-24%
Разработчик IoT Мониторинг и логирование: Zabbix, Prometheus, ELK MongoDB
-30%
DevOps практики и инструменты MS SQL Server Developer SRE практики и инструменты Administrator Linux. Advanced Infrastructure as a code Супер-интенсив "Tarantool" Специализация Network engineer
Корпоративные курсы
Экспресс-курс по управлению миграциями (DBVC) Экспресс-курс «IaC Ansible» Разработчик программных роботов (RPA) на базе UiPath и PIX Внедрение и работа в DevSecOps NoSQL Spark Developer Экспресс-курс «CI/CD или Непрерывная поставка с Docker и Kubernetes» Game QA Engineer IT-Recruiter Enterprise Architect Node.js Developer Cloud Solution Architecture Agile Project Manager Супер-практикум по работе с протоколом BGP Infrastructure as a code Промышленный ML на больших данных Супер-интенсив Azure Руководитель поддержки пользователей в IT
Специализации Курсы в разработке Подготовительные курсы Подписка
+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

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

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