Шпион Шинона не работает, хотя функция шпионажа вызывается - PullRequest
0 голосов
/ 08 января 2019

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

Скажем, у меня есть что-то следующее:

index.js

let MyModule = require('./src/index.js');

MyModule = new MyModule();

module.exports = {
  DoStuff: MyModule.DoStuff,
  doOtherStuff: MyModule.doOtherStuff,
};

ЦСИ / index.js

const MyModule = function MyModule() {

  const self = this;

  self.doOtherStuff = function doOtherStuff() {
    console.log('doOtherStuff called!!!')
  }

  self.DoStuff = async function DoStuff() {
    const xhr = self.axiosInstance();
    await xhr.post()
      .then((res) => {
        self.doOtherStuff(res.data);
      })
      .catch((_err) => {
        console.log(_err);
      });
  };
}

module.exports = MyModule;

Мой тест выглядит следующим образом:

const nock = require('nock');
const sinon = require('sinon');
const MyModule = require('../index.js');
describe('When calling DoStuff succeeds in making the xhr call', () => {
        before(() => {
          nock(apiHostName)
            .post('/some-path')
            .reply(200, { foo: 'bar' });
        });
        it('should call doOtherStuff', async () => {
          const spy = sinon.spy(MyModule, 'doOtherStuff');
          await MyModule.DoStuff();
          sinon.assert.calledOnce(spy);
        });
      });

Я вижу журнал консоли в выходных данных моей функции doOtherStuff в выходных данных моего тестового прогона, но тест завершается неудачно, сообщая, что шпион вызывался ноль раз.

Мне было интересно, связано ли это с асинхронной природой кода, который я тестирую, но я убедился, что в своем тесте я использовал async / await. Должно быть, я делаю что-то глупое, где я не так?

Спасибо

UPDATE

Итак, я попытался вернуть функции к чему-то более простому, и теперь у меня есть следующее:

const MyModule = function MyModule() {

  const self = this;

  self.doOtherStuff = function doOtherStuff() {
    console.log('doOtherStuff called!!!')
  }

  self.DoStuff = function DoStuff() {
    self.doOtherStuff();
  };
}

module.exports = MyModule;

Так что это исключит любые проблемы с асинхронностью / ожиданием, которые могут возникнуть.

Но даже при выполнении следующего простого теста, шпион не вызывается:

const MyModule = require('../index.js');

it('should call doOtherStuff', () => {
  const spy = sinon.spy(MyModule, 'doOtherStuff');
  MyModule.DoStuff();
  sinon.assert.calledOnce(spy);
});

Если я шпионю за console.log, тогда это проходит. Должно быть, я неправильно понимаю очень простой принцип, но я не знаю, что это такое!

Это как-то связано с тем, как мои module.exports были объявлены? Поэтому, хотя я пытаюсь шпионить за экспортом верхнего уровня в моем index.js (doOtherStuff: MyModule.doOtherStuff), это не то, что на самом деле вызывается внутри, когда в моем тесте выполняется вызов DoStuff?

1 Ответ

0 голосов
/ 08 января 2019

Выпуск

Свойство, заключенное в spy, не является вызываемым свойством.

Подробнее

sinon.spy берет объект и имя свойства и упаковывает функцию в это имя свойства в шпионе.

В этом случае объектом является модуль экспорта index.js.

Модуль экспорта - это объект с двумя свойствами, которые указывают на методы внутреннего экземпляра MyModule, созданного в index.js. Таким образом, свойство doOtherStuff этого объекта теперь является spy, а свойство DoStuff по-прежнему является просто ссылкой на свойство DoStuff внутреннего экземпляра MyModule.

Когда тест затем вызывает MyModule.DoStuff(), он вызывает свойство DoStuff внутреннего экземпляра MyModule, которое вызывает свойство doOtherStuff внутреннего экземпляра MyModule, который регистрируется на консоли.

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

spy в свойстве doOtherStuff объекта, экспортируемого с помощью index.js, затем правильно подтверждает, что он был вызван 0 раз.

Решение

Убедитесь, что spy создано для свойства, которое фактически вызывается.

Самый простой способ сделать это в этом случае - напрямую экспортировать экземпляр MyModule из index.js:

let MyModule = require('./src/index.js');

MyModule = new MyModule();

module.exports = MyModule;

Теперь, когда spy создан, он создается непосредственно в свойстве doOtherStuff внутреннего экземпляра MyModule и правильно сообщит, что он был вызван один раз.

...