функция jest.spyOn, которая будет вызвана после возврата результата - PullRequest
0 голосов
/ 20 февраля 2019

Предположим, у нас есть класс с некоторыми методами.Мы хотим следить за тем, вызывается ли метод B или нет, тогда как после выполнения methodA вернет результат вызывающей стороне, а methodB будет выполняться асинхронно.Класс выглядит следующим образом.

class Parent {
    constructor() {
        this.conf = [{ id:'1', func: Parent.methodA.bind(Parent)}, { id:'2', func: Parent.methodB.bind(Parent)}]
    }
    static methodA() {
        console.log('methodA is called from methodC');
        return 'methodA';
    }
    static methodB() {
        console.log('methodB is called from methodC');
        return 'methodB';
    }
    methodC(conf) {
        conf.forEach((eachConf) => {
            if(eachConf.id === '1') {
                setImmediate(() => {
                    // Just to call method with conf = [{ id:'2', func: this.methodB.bind(this)}]
                    this.methodC(conf.slice(1));
                })
                return eachConf.func();
            }
            return eachConf.func();
        });
    }
}
module.exports = Parent;

В файле jest test вызывается methodC, и мы хотим, чтобы methodA возвращало значение, и хотим, чтобы methodB также вызывался.testSpy.js const Parent = require ('./ parent');

it('check methodA and methodB called', async () => {
    const methodA = jest.spyOn(Parent, 'methodA');
    const methodB = jest.spyOn(Parent, 'methodB');
    const instance = new Parent();
    instance.methodC(instance.conf);
    expect(methodA).toHaveBeenCalled();
    //How to spyOn methodB.
    //expect(methodB).toHaveBeenCalled();
});

Может быть несколько методов для запуска после возврата результата.Хочется убедиться, что все они выполнены, и было бы лучше получить результат каждого шага тоже.

Ответы [ 2 ]

0 голосов
/ 20 февраля 2019

.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.

0 голосов
/ 20 февраля 2019

Когда вы используете setImmediate, вам нужно использовать jest.useFakeTimers() и jest.runAllTimers(), чтобы немедленно вызывать каждый обратный вызов, который вы положили в setImmediate.

it('check methodA and methodB called', async () => {
    jest.useFakeTimers()
    const methodA = jest.spyOn(Parent, 'methodA');
    const methodB = jest.spyOn(Parent, 'methodB');
    Parent.methodC(Parent.conf);
    jest.runAllTimers()
    expect(methodA).toHaveBeenCalled();
    //How to spyOn methodB.
    //expect(methodB).toHaveBeenCalled();
});

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...