javascript - 测试中未涵盖的回调函数 - 如何模拟?
问题描述
我正在测试以下方法:
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);
};
有没有办法可以以某种方式模拟对回调方法的调用?
解决方案
使用Proxy为模拟对象创建一个代理,它可以拦截和重新定义该对象的基本操作。这意味着我们可以使用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
推荐阅读
- sql - 使用 UNION ALL 的嵌套查询的 SQL JSON 对象返回字符串
- c# - 在 MVC 5 上从本地网络读取图像
- java - 想让图在面板下方
- c# - 异步回调在 BeginReceive 中不起作用
- php - 为什么这个 cURL 发布请求登录不起作用?
- jquery - 如何在 jquery 中单击 id 获取子属性值?
- azure - 将全局自定义遥测初始化程序添加到 Azure Function App 中的 Application Insights
- opencart - 谷歌搜索控制台中的购物车页面出现软 404 错误
- android - 如何解析包含没有名称的数组的 JSON 对象
- arrays - 将 tableView 中的项目与选定项目进行比较