#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
});