Тестирование в JavaScript требует применения различных подходов для проверки поведения кода. Одними из самых важных инструментов для имитации зависимостей являются mock, stub и spy. Несмотря на то, что все эти объекты служат схожей цели — заменяют реальные зависимости в тестах — каждый из них имеет свою специфику и применяется в определенных ситуациях. Разбор этих понятий поможет разобраться в их использовании и понять, когда следует использовать каждый из них.
Mock — это объект, который замещает реальные
зависимости и предназначен для проверки взаимодействия между объектами.
Моки используются для того, чтобы удостовериться, что определенные
методы были вызваны с нужными аргументами и в нужный момент. Они
создаются с помощью методов библиотеки для мокинга, таких как
jasmine.createSpyObj() в Jasmine.
Основной особенностью mock-объектов является то, что они могут быть настроены на выполнение конкретных действий, а также проверку того, как использовались их методы в ходе тестирования.
Пример создания mock-объекта:
const mockService = jasmine.createSpyObj('service', ['fetchData']);
mockService.fetchData.and.returnValue(Promise.resolve({ data: [] }));
В приведенном примере mockService — это объект, у
которого есть метод fetchData, который будет возвращать
промис с пустым массивом. Этот объект можно использовать в тестах для
проверки того, как компонент взаимодействует с сервисом.
Mock-объекты полезны, когда необходимо контролировать поведение внешних зависимостей и убедиться, что определенные методы вызываются с правильными аргументами.
Stub — это объект, который замещает реальные зависимости, но в отличие от mock, основная цель стуба — предоставить заранее определенное поведение для конкретного метода или функции. Стубы не проверяют взаимодействие, как моки, а просто предоставляют заранее установленное поведение. Стубы применяются, когда нужно, чтобы зависимость возвращала конкретные данные, не вмешиваясь в логику работы тестируемого кода.
Суть стуба в том, чтобы предотвратить выполнение реальной логики и контролировать поведение функции или метода. Например, вместо того чтобы вызывать реальную API-функцию, можно подставить заглушку, которая вернет заранее заданные данные.
Пример создания стуба:
const service = {
fetchData: jasmine.createSpy('fetchData').and.returnValue(Promise.resolve({ data: [] }))
};
Здесь fetchData — это стуб, который всегда возвращает
пустой массив, когда его вызывают. Стубы полезны, когда нужно
изолировать тестируемый код от сторонних зависимостей или когда важно
вернуть заранее известные результаты.
Spy — это объект, который используется для отслеживания того, как вызываются методы. Спай не заменяет реализацию метода, а просто “наблюдает” за его вызовами. Основная цель спая — собрать информацию о том, был ли вызван метод, с какими аргументами и сколько раз он был вызван.
В отличие от мока, спай не проверяет, какой результат был возвращен, а только фиксирует информацию о вызовах. Спай полезен для проведения проверок на взаимодействие с методами, особенно когда необходимо удостовериться, что метод был вызван, и какие именно аргументы были переданы.
Пример создания спая:
const service = {
fetchData: jasmine.createSpy('fetchData')
};
service.fetchData('param');
expect(service.fetchData).toHaveBeenCalledWith('param');
В данном примере создается спай на метод fetchData.
Когда он вызывается с аргументом 'param', проверка
утверждает, что метод был вызван с ожидаемым параметром.
Назначение:
Проверки:
Когда использовать:
Использование mock, stub и spy в тестах зависит от цели тестирования и характера зависимостей. Mock-объекты полезны для проверки взаимодействий между компонентами, стубы — для замены реальных зависимостей и контроля их поведения, а спаи — для наблюдения за вызовами методов. Правильный выбор подхода позволяет создавать более точные и эффективные тесты, обеспечивая корректное поведение программы.