Моки и стабы — это два ключевых подхода к созданию имитаций объектов в юнит-тестах. Эти техники активно применяются для изоляции компонентов системы и проверки их поведения в контролируемой среде. Хотя термины часто используются как синонимы, их значения и применения различаются, и понимание различий между ними важно для эффективного тестирования.
Стаб — это объект или компонент, который используется в тестах для имитации поведения реальных зависимостей. Его основная цель — возвращать заранее заданные значения, когда происходит вызов его методов. Стаб используется для того, чтобы изолировать тестируемую единицу и предоставить фиксированное поведение для зависимостей.
Стаб может быть простым объектом с жестко зафиксированным результатом, например:
const databaseStub = {
getUserById: (id) => ({ id, name: 'John Doe' }),
};
function getUserInfo(id, db) {
const user = db.getUserById(id);
return user.name;
}
console.log(getUserInfo(1, databaseStub)); // John Doe
В этом примере databaseStub — это стаб, который
подставляет заранее заданные данные при вызове метода
getUserById. Тестируемая функция не зависит от настоящей
базы данных, а использует стаб в качестве замены.
Мок отличается от стаба тем, что помимо возвращения заданных значений, он также отслеживает, как именно используются его методы: какие аргументы передаются, сколько раз вызываются методы и в каком порядке. Это дает возможность проводить более глубокие проверки поведения системы.
Моки обычно используются для проверки того, что взаимодействие между компонентами происходит в соответствии с ожидаемым сценарием.
Пример использования мока с библиотекой, такой как
jest:
const userService = {
getUserById: jest.fn().mockReturnValue({ id: 1, name: 'John Doe' }),
};
function getUserInfo(id, service) {
const user = service.getUserById(id);
return user.name;
}
console.log(getUserInfo(1, userService)); // John Doe
// Проверка, что метод getUserById был вызван
expect(userService.getUserById).toHaveBeenCalledWith(1);
Здесь userService.getUserById является мок-методом.
Помимо того, что он возвращает заранее заданные данные, мы также можем
проверить, был ли вызван этот метод с нужными аргументами, сколько раз
он был вызван и т.д.
Цель:
Ожидаемое поведение:
Применение:
Библиотека tingle.js — это легковесный модальный плагин, который используется для создания модальных окон. При тестировании компонентов, использующих tingle.js, может возникнуть необходимость в использовании моков и стабов для имитации поведения зависимостей.
Рассмотрим пример, где нужно протестировать компонент, который открывает модальное окно с использованием tingle.js. Вместо того чтобы взаимодействовать с реальным модальным окном в тестах, можно использовать стаб или мок.
Пример с моками для tingle.js:
import tingle from 'tingle.js';
const modalMock = jest.fn().mockImplementation(() => ({
open: jest.fn(),
close: jest.fn(),
}));
function openModal(modal) {
modal.open();
}
const modal = modalMock();
openModal(modal);
expect(modal.open).toHaveBeenCalled();
В этом примере используется мок, чтобы отслеживать вызов метода
open в объекте модального окна, создаваемом библиотекой
tingle.js.
Когда использовать стаб:
Когда использовать мок:
Одной из распространенных сложностей в тестировании является излишняя сложность моков и стабов. Важно помнить, что моки и стабы должны быть максимально простыми и отражать только необходимое поведение. Переусложнение тестов может привести к трудностям в поддержке и понимании кода.
Также стоит отметить, что моки и стабы могут быть излишними в некоторых случаях, когда тестируемая единица не имеет сложных зависимостей. В таких ситуациях, например, можно использовать прямые функции или фиктивные объекты, чтобы упростить тестирование.
Моки и стабы играют ключевую роль в юнит-тестировании, позволяя изолировать компоненты и проверять их взаимодействие с зависимостями. Правильный выбор между ними зависит от целей тестирования — моки больше ориентированы на проверку взаимодействий, а стабы — на имитацию поведения зависимостей. Важно использовать их обоснованно, чтобы не усложнять процесс тестирования и сделать код тестов понятным и поддерживаемым.