#javascript #angular #typescript #unit-testing #jestjs
Вопрос:
Я тестирую следующий метод:
startScriptLoad(): void {
const documentDefaultView = this.getDocumentDefaultView();
if (documentDefaultView) {
const twitterData: ICourseContentElementEmbedTweetWidgetData = this.getTwitterWidgetData() ?? {
// eslint-disable-next-line @typescript-eslint/no-empty-function
ready: () => {},
_e: [],
};
if (this.scriptExists()) {
((this.document.defaultView as unknown) as ICourseContentElementEmbedTweetDocument)[
this.TWITTER_OBJECT
] = twitterData;
return;
}
this.appendScriptToDOM();
twitterData._e = [];
twitterData.ready = (callback: () => void) => {
twitterData._e.push(callback);
};
((this.document.defaultView as unknown) as ICourseContentElementEmbedTweetDocument)[
this.TWITTER_OBJECT
] = twitterData;
}
}
с помощью следующего теста:
describe('startScriptLoad()', () => {
it('should load script', () => {
jest.spyOn(service, 'getDocumentDefaultView');
jest.spyOn(service, 'appendScriptToDOM');
service.startScriptLoad();
expect(service.getDocumentDefaultView).toHaveBeenCalled();
expect(service.appendScriptToDOM).toHaveBeenCalled();
});
});
По какой-то причине я не могу получить покрытие для следующих строк кода в startScriptLoad():
twitterData.ready = (callback: () => void) => {
twitterData._e.push(callback);
};
Есть ли способ каким-то образом имитировать вызов метода обратного вызова?
Ответ №1:
Используйте прокси-сервер для создания прокси-сервера для издевательского объекта, который может перехватывать и переопределять основные операции для этого объекта. Это означает, что мы можем использовать handler.set (), чтобы настроить ловушку для установки ready
частного метода на mTwitterData
объекте.
Ловушка заключается в следующем: назначьте ready
анонимный метод переменной типа _ready
. После его получения вызовите его вручную для последующего тестирования.
service.ts
:
export class SomeService {
getTwitterWidgetData() {
return {} as any;
}
startScriptLoad(): void {
const twitterData = this.getTwitterWidgetData();
twitterData._e = [];
twitterData.ready = (callback: () => void) => {
twitterData._e.push(callback);
};
}
}
service.test.ts
:
import { SomeService } from './service';
describe('69041800', () => {
test('should pass', () => {
const service = new SomeService();
let _ready;
const mTwitterData = new Proxy({} as any, {
set: (obj, prop, value) => {
if (prop === 'ready') {
_ready = value;
}
obj[prop] = value;
return true;
},
});
const getTwitterWidgetDataSpy = jest.spyOn(service, 'getTwitterWidgetData').mockReturnValue(mTwitterData);
service.startScriptLoad();
expect(getTwitterWidgetDataSpy).toBeCalledTimes(1);
// test ready private method
const mCallback = jest.fn();
_ready(mCallback);
expect(mTwitterData._e).toEqual([mCallback]);
getTwitterWidgetDataSpy.mockRestore();
});
});
результат теста:
PASS examples/69041800/service.test.ts (9.519 s)
69041800
✓ should pass (4 ms)
------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
------------|---------|----------|---------|---------|-------------------
All files | 83.33 | 100 | 66.67 | 83.33 |
service.ts | 83.33 | 100 | 66.67 | 83.33 | 3
------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 10.148 s