Различия между mock, stub, spy

Тестирование в JavaScript требует применения различных подходов для проверки поведения кода. Одними из самых важных инструментов для имитации зависимостей являются mock, stub и spy. Несмотря на то, что все эти объекты служат схожей цели — заменяют реальные зависимости в тестах — каждый из них имеет свою специфику и применяется в определенных ситуациях. Разбор этих понятий поможет разобраться в их использовании и понять, когда следует использовать каждый из них.

Mock

Mock — это объект, который замещает реальные зависимости и предназначен для проверки взаимодействия между объектами. Моки используются для того, чтобы удостовериться, что определенные методы были вызваны с нужными аргументами и в нужный момент. Они создаются с помощью методов библиотеки для мокинга, таких как jasmine.createSpyObj() в Jasmine.

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

Пример создания mock-объекта:

const mockService = jasmine.createSpyObj('service', ['fetchData']);
mockService.fetchData.and.returnValue(Promise.resolve({ data: [] }));

В приведенном примере mockService — это объект, у которого есть метод fetchData, который будет возвращать промис с пустым массивом. Этот объект можно использовать в тестах для проверки того, как компонент взаимодействует с сервисом.

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

Stub

Stub — это объект, который замещает реальные зависимости, но в отличие от mock, основная цель стуба — предоставить заранее определенное поведение для конкретного метода или функции. Стубы не проверяют взаимодействие, как моки, а просто предоставляют заранее установленное поведение. Стубы применяются, когда нужно, чтобы зависимость возвращала конкретные данные, не вмешиваясь в логику работы тестируемого кода.

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

Пример создания стуба:

const service = {
  fetchData: jasmine.createSpy('fetchData').and.returnValue(Promise.resolve({ data: [] }))
};

Здесь fetchData — это стуб, который всегда возвращает пустой массив, когда его вызывают. Стубы полезны, когда нужно изолировать тестируемый код от сторонних зависимостей или когда важно вернуть заранее известные результаты.

Spy

Spy — это объект, который используется для отслеживания того, как вызываются методы. Спай не заменяет реализацию метода, а просто “наблюдает” за его вызовами. Основная цель спая — собрать информацию о том, был ли вызван метод, с какими аргументами и сколько раз он был вызван.

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

Пример создания спая:

const service = {
  fetchData: jasmine.createSpy('fetchData')
};

service.fetchData('param');
expect(service.fetchData).toHaveBeenCalledWith('param');

В данном примере создается спай на метод fetchData. Когда он вызывается с аргументом 'param', проверка утверждает, что метод был вызван с ожидаемым параметром.

Сравнение mock, stub и spy

  1. Назначение:

    • Mock — проверяет взаимодействие, что и как вызывается в тестируемом коде.
    • Stub — заменяет поведение метода, предоставляя заранее установленное поведение.
    • Spy — отслеживает вызовы метода, не изменяя его поведение.
  2. Проверки:

    • Mock — проверяет, был ли вызван метод и с какими аргументами.
    • Stub — не проверяет, а предоставляет поведение, которое заранее определено.
    • Spy — фиксирует информацию о вызовах, но не изменяет результат работы метода.
  3. Когда использовать:

    • Mock — когда необходимо проверить, что методы были вызваны с правильными аргументами и в правильный момент.
    • Stub — когда нужно вернуть заранее известные данные и изолировать код от внешних зависимостей.
    • Spy — когда важно отслеживать вызовы методов и убедиться, что они вызываются нужное количество раз или с нужными аргументами.

Заключение

Использование mock, stub и spy в тестах зависит от цели тестирования и характера зависимостей. Mock-объекты полезны для проверки взаимодействий между компонентами, стубы — для замены реальных зависимостей и контроля их поведения, а спаи — для наблюдения за вызовами методов. Правильный выбор подхода позволяет создавать более точные и эффективные тесты, обеспечивая корректное поведение программы.