Вот упрощенный рабочий пример для начала работы:
// @ts-ignore
import * as Api from 'npm-module'; // <= (ts-ignore since "npm-module" doesn't exist)
import EventEmitter from 'events';
jest.mock('npm-module', () => {
const getSomethingMock = jest.fn(); // <= always return...
const onUpdateMock = jest.fn(); // <= ...the same mocks...
return {
Rest: () => ({ getSomething: getSomethingMock }),
Websocket: () => ({ onUpdate: onUpdateMock })
}
},
{ virtual: true }); // <= (use virtual since "npm-module" doesn't exist)
class Component {
private _rest: any;
private _websocket: any;
public events = new EventEmitter();
constructor() {
this._rest = new Api.Rest();
this._websocket = new Api.Websocket();
this._init();
}
private _init() {
this._websocket.onUpdate((data) => { // <= ...so that this onUpdate...
this.events.emit('update', data);
});
}
}
test('Component', () => {
const component = new Component();
const listener = jest.fn();
component.events.on('update', listener);
const onUpdate = new Api.Websocket().onUpdate; // <= ...is the same as this one
const onUpdateArrowFunction = onUpdate.mock.calls[0][0]; // <= get the arrow function passed to it
onUpdateArrowFunction('mock data'); // <= now call the function
expect(listener).toHaveBeenCalledWith('mock data'); // Success!
});
Детали
Jest
захватывает систему require
и позволяет вам указать, что вы хотите, чтобы он возвращал, когда требуется модуль (обратите внимание, что операторы TypeScript import
компилируются в вызовы require
).
Один из способов смоделировать модуль - создать ручной макет , создав в __mocks__/npm-module.ts
файл, содержащий вашу макет.
Другой способ (см. Выше) - использовать jest.mock
и передать ему заводскую функцию модуля.
Всякий раз, когда модуль требуется во время теста, Jest
возвращает вместо этого проверенный модуль.
Обратите внимание, что приведенный выше пример всегда возвращает один и тот же макет для getSomething
и onUpdate
, поэтому эти фиктивные функции можно получить во время теста.
Также обратите внимание на использование mockFn.mock.calls
для извлечения этой функции стрелки:
(data) => {
this.events.emit('update', data);
}
... который передается onUpdate
. После того, как он был извлечен, его можно вызвать напрямую, что вызовет слушателя, как и ожидалось.