Функції-імітації
Функції-імітації значно спрощують тестування пов’язаного коду, надаючи можливість стирати справжню імплементацію функцї, записувати виклики функції (і параметри, які були їй передані), записувати екземпляри, які повертає функція-конструктор, викликана з допомогою оператора new
і вказувати значення, які має повернути функція під час тестування.
Існує два способи створення функцій-імітацій: створення в коді тестів або написання ручної імітації
для перевизначення залежност і модуля.
Використання функцій-імітацій
Давайте уявимо, що ми тестуємо реалізацію функції forEach
, яка викликає коллбек для кожного елементу в наданому масиві.
export function forEach(items, callback) {
for (const item of items) {
callback(item);
}
}
Щоб протестувати цю функцію, ми можемо використати функцію-імітацію і перевірити її стан, щоб переконатися, що зворотній виклик був викликаний, як і очікувалося.
const forEach = require('./forEach');
const mockCallback = jest.fn(x => 42 + x);
test('forEach mock function', () => {
forEach([0, 1], mockCallback);
// Функція-імітація викликається двічі
expect(mockCallback.mock.calls).toHaveLength(2);
// Перший аргумент першого виклику функції був 0
expect(mockCallback.mock.calls[0][0]).toBe(0);
// Перший аргумент другого виклику функції був 1
expect(mockCallback.mock.calls[1][0]).toBe(1);
// Повернене значення першого виклику функції було 42
expect(mockCallback.mock.results[0].value).toBe(42);
});
Властивість .mock
Всі функції-імітації мають спеціальну властивість .mock
, де зберігається інформація про те, як функція була викликана і які значення вона повертала. Властивість .mock
також відстежує значення this
для кожного виклику, що дозволяє вивчати їх пізніше:
const myMock1 = jest.fn();
const a = new myMock1();
console.log(myMock1.mock.instances);
// > [ <a> ]
const myMock2 = jest.fn();
const b = {};
const bound = myMock2.bind(b);
bound();
console.log(myMock2.mock.contexts);
// > [ <b> ]
Наступні властивості функцій-імітацій дуже корисні в тестах для перевірки того, як ці функції були викликані, які екземпляри були створені або які значення вони повернули:
// Функція викликається рівно один раз
expect(someMockFunction.mock.calls).toHaveLength(1);
// Перший аргумент першого виклику функції був 'first arg'
expect(someMockFunction.mock.calls[0][0]).toBe('first arg');
// Другий аргумент першого виклику функції був 'second arg'
expect(someMockFunction.mock.calls[0][1]).toBe('second arg');
// Повернене значення першого виклику функції було 'return value'
expect(someMockFunction.mock.results[0].value).toBe('return value');
// Функція викликається з певним контекстом `this`: об'єкт `element`.
expect(someMockFunction.mock.contexts[0]).toBe(element);
// Екземпляри цієї функції створюються рівно двічі
expect(someMockFunction.mock.instances.length).toBe(2);
// Перший екземпляр функції повертає об'єкт
// з властивістю `name`, значення якої 'test'
expect(someMockFunction.mock.instances[0].name).toBe('test');
// Перший аргумент останнього виклику функції був 'test'
expect(someMockFunction.mock.lastCall[0]).toBe('test');
Імітація повернених значень
Функції-імітації також можуть бути використані, щоб передавати тестові значення у ваш код під час тесту:
const myMock = jest.fn();
console.log(myMock());
// > undefined
myMock.mockReturnValueOnce(10).mockReturnValueOnce('x').mockReturnValue(true);
console.log(myMock(), myMock(), myMock(), myMock());
// > 10, 'x', true, true