Создание spy объектов с createSpyObj

Jasmine предоставляет мощный инструмент для тестирования JavaScript-кода через spy объекты. Одним из самых удобных способов создания таких объектов является функция createSpyObj. Она позволяет быстро генерировать объект с методами-шпионами, отслеживающими вызовы и аргументы, без необходимости писать отдельные функции вручную.

Основные концепции createSpyObj

Функция createSpyObj используется для имитации объекта, предоставляя набор методов, которые можно наблюдать и контролировать в тестах. Синтаксис базовый:

const spyObject = jasmine.createSpyObj(baseName, methodNames);
  • baseName — строка, которая служит префиксом в отчетах Jasmine. Она помогает различать объекты-шпионы в логах тестов.
  • methodNames — массив строк, каждая из которых будет именем метода-шпиона.

Пример:

const calculator = jasmine.createSpyObj('Calculator', ['add', 'subtract', 'multiply']);

В этом случае создается объект calculator с методами add, subtract и multiply, которые являются spy-функциями.

Проверка вызовов методов

Spy-функции отслеживают, сколько раз был вызван метод, с какими аргументами, и возвращают информацию для утверждений (expect).

calculator.add(2, 3);
calculator.add(4, 5);

expect(calculator.add).toHaveBeenCalled();
expect(calculator.add).toHaveBeenCalledTimes(2);
expect(calculator.add).toHaveBeenCalledWith(2, 3);
expect(calculator.add).toHaveBeenCalledWith(4, 5);

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

Настройка возвращаемых значений

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

calculator.add.and.returnValue(10);
calculator.subtract.and.returnValues(1, 2, 3); // последовательные вызовы

Другие методы настройки:

  • and.callFake(fn) — заменяет поведение метода произвольной функцией.
  • and.throwError('Ошибка') — заставляет метод выбрасывать исключение.
  • and.returnValue(value) — возвращает одно фиксированное значение.
  • and.returnValues(...values) — возвращает значения последовательно при каждом вызове.

Использование spy объектов для имитации зависимостей

Чаще всего createSpyObj применяется для замены внешних зависимостей, таких как сервисы, API или модули, чтобы изолировать тестируемый компонент.

Пример с сервисом:

const userService = jasmine.createSpyObj('UserService', ['getUser', 'saveUser']);

userService.getUser.and.returnValue({ id: 1, name: 'John Doe' });
userService.saveUser.and.callFake(user => ({ ...user, saved: true }));

const userController = new UserController(userService);

userController.saveUser({ id: 1, name: 'John Doe' });

expect(userService.getUser).not.toHaveBeenCalled();
expect(userService.saveUser).toHaveBeenCalledWith({ id: 1, name: 'John Doe' });

В этом примере тестируется UserController без фактического обращения к базе данных или внешнему API.

Плюсы createSpyObj перед ручной имитацией

  • Экономия времени — не требуется писать отдельные spy-функции.
  • Удобство тестирования взаимодействий — встроенные методы toHaveBeenCalled, toHaveBeenCalledWith и другие.
  • Гибкость конфигурации — возможность возвращать значения, бросать ошибки или вызывать произвольные функции.
  • Чистота тестов — код становится проще и легче поддерживается, особенно при работе с большим количеством зависимостей.

Дополнительные возможности

  1. Создание объекта с доступом к свойствам: начиная с Jasmine 3.5, createSpyObj позволяет определять не только методы, но и свойства через объект конфигурации:
const obj = jasmine.createSpyObj('Obj', ['method1'], { prop1: 42 });
expect(obj.prop1).toBe(42);
  1. Переименование методов в логах: использование baseName помогает различать одинаковые методы разных объектов в отчетах.

  2. Совместимость с TypeScript: для строгой типизации можно комбинировать createSpyObj с интерфейсами, чтобы получать автодополнение и проверки типов.

Практические рекомендации

  • Использовать createSpyObj для всех зависимостей, которые не требуют реальной логики.
  • Настраивать возвращаемые значения только там, где они критичны для теста.
  • Проверять вызовы spy-функций вместо реального состояния системы, чтобы тесты оставались быстрыми и предсказуемыми.
  • Комбинировать and.callFake с returnValue там, где нужно эмулировать более сложное поведение метода.

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