.bind
создает новую функцию , поэтому func
устанавливается на новую функцию, созданную this.methodA.bind(this)
.
При запуске jest.spyOn(Parent, 'methodA');
она заменяет methodA
нашпион, но это никак не влияет на func
.
Когда вызывается func
, вызывается новая функция, а шпион на methodA
никогда не вызывается.
Вы должны убедиться, что spy
вызывается, если вы хотите использовать его для проверки того, что methodA
был вызван.
В этом случае вместо привязки methodA
к this
с использованием bind
(который создает новую функцию), вы можете вызывать this.methodA
из функции стрелки (так как функции стрелки захватывают this
лексической области видимости ... в данном случае this
из конструктора):
constructor() {
this.conf = [
{
id: '1',
func: (...args) => this.methodA(...args)
},
{
id: '2',
func: (...args) => this.methodB(...args)
}
];
}
Затем, когда вызывается func
, он вызывает methodA
, который вызовет spy
, и тест пройдет.
Обновление
Вот рабочий тест для вашего обновленного примера кода:
it('check methodA and methodB called', async () => {
jest.useFakeTimers();
const methodA = jest.spyOn(Parent, 'methodA');
const methodB = jest.spyOn(Parent, 'methodB');
const instance = new Parent();
instance.methodC(instance.conf);
jest.runAllTimers();
expect(methodA).toHaveBeenCalledTimes(1); // SUCCESS
expect(methodB).toHaveBeenCalledTimes(2); // SUCCESS
});
jest.useFakeTimers
заменяет функции таймера, такие как setImmediate
с насмешками, которые помнят, как их называли.Затем jest.runAllTimers
запускает все обратные вызовы, запланированные с помощью функций таймера.
methodA
вызывается при первом вызове methodC
.
methodB
вызывается при первом вызове methodC
вызывается, а также вызывается, когда methodC
вызывается снова в результате обратного вызова setImmediate
.