Spy возвращает callcount 0 при использовании в качестве свойства объекта

#typescript #unit-testing #mocha.js #sinon

#typescript #модульное тестирование #mocha.js #sinon

Вопрос:

Я пытаюсь написать тест, который проверяет, были ли вызваны функции библиотеки третьей части.

Тест: (мокко)

 describe('SomeClassTest', () => {
  describe('Setup', () => {
    beforeEach(() => {
      const channel = {createChannel: () => 'channel created'};
      // @ts-ignore
      this.channelSpy = Sinon.spy(channel, 'createChannel');
      // @ts-ignore
      Sinon.stub(amqplib, 'connect').returns(channel);
  });
    // @ts-ignore
    afterEach(() => amqplib.connect.restore());

    it('Should check if SomeClass has created Channel', () => {
      const someclass = SomeClass.getInstance();
      someclass.init();

      // @ts-ignore
      expect(amqplib.connect.callCount).to.be.eq(1); // True
      // @ts-ignore
      expect(this.channelSpy.callCount).to.be.eq(1); // False :(
    });
  });
});
  

Класс:

 export default class SomeClass {

  private connection?: amqplib.Connection;

  public async init() {
    await this.connect();
    await this.createChannel();
  }

  private async connect(): Promise<void> {
    this.connection = await amqplib.connect(this.connectionOptions);
  }

  private async createChannel(): Promise<void> {
    if (!this.connection) {
      throw new Error('Some Error :)');
    }
    this.channel = await this.connection.createChannel();
  }
}
  

Я уверен, что this.connection.CreateChannel() был вызван, но тесты не хотят это доказывать, кто-нибудь поможет моей бедной душе?:)

Ответ №1:

При Promise разрешении обратный вызов помещается в очередь PromiseJobs, которая обрабатывается после завершения текущего запущенного сообщения.

В этом случае ваши функции ставят в очередь обратные вызовы в PromiseJobs, а текущее запущенное сообщение является самим тестом, поэтому тест выполняется до завершения, прежде чем задания, поставленные в очередь в PromiseJobs, получат возможность выполнить.

Поскольку задания в PromiseJobs еще не запущены, тест завершается неудачно, когда доходит до теста для channelSpy , поскольку он еще не был вызван.


Promise Возвращаемый by init уже привязан к Promises возвращаемому by connect и createChannel , поэтому все, что вам нужно сделать, это создать свою тестовую функцию async , а затем вызвать await Promise возвращаемый by init :

 it('Should check if SomeClass has created Channel', async () => {  // async test function
  const someclass = SomeClass.getInstance();
  await someclass.init();  // await the Promise returned by init

  // @ts-ignore
  expect(amqplib.connect.callCount).to.be.eq(1); // True
  // @ts-ignore
  expect(this.channelSpy.callCount).to.be.eq(1); // True
});