angular - 单元测试 Angular 11 服务存根问题
问题描述
我正在尝试对我的组件进行单元测试。
组件.ts:
async ngOnInit(): Promise<void> {
await this.dataProviderService.getCurrencyCodesList().then(data => {
this.currencyList = data;
});
this.currencyList.sort((a, b) => {
return a.code > b.code ? 1 : -1;
});
// ...
}
使用的服务方法:
async getCurrencyCodesList(): Promise<any[]> {
// ...
const currencyCodes = currencyList.map(data => {
return {code: data.code, currency: data.currency, table: data.table};
});
return currencyCodes;
}
在 spec.ts 文件中,我尝试创建一个存根
//...
it('should have currencies in the list', () => {
expect(component.currencyList.length).toBeGreaterThan(1);
});
});
class DataProviderServiceStub {
async getCurrencyCodesList(): Promise<Observable<any[]>> {
return of ([{code: 'PLN', table: 'A'},
{code: 'EUR', table: 'A'}]);
}
}
// then this:
class DataProviderServiceStub {
async getCurrencyCodesList(): Promise<any[]> {
return ([{code: 'PLN', table: 'none'},
{code: 'EUR', table: 'A'}]);
}
}
//also tried return (of)([]), ([{}]) etc.
问题是我在从存根获得的数组上使用 .sort 时遇到了这样的 Karma 错误:
Error: Uncaught (in promise): TypeError: this.currencyList.sort is not a function
TypeError: this.currencyList.sort is not a function
它有时会以错误的形式出现,有时会以 AfterAll 错误的形式出现,有时它会说一切都很好。我究竟做错了什么?
测试结果失败:“TypeError:无法读取未定义的属性‘长度’”
解决方案
一旦 OnInit 被调用,这个块就会被执行:
this.dataProviderService.getCurrencyCodesList()
接下来,then
将块推送到微任务队列并安排调用:
.then(data => {
this.currencyList = data;
});
然后继续进行,this.currencyList.sort
因为then
block 仍在排队并且 promise 仍未解决,因此没有分配任何内容currencyList
,因此它包含undefined
在启动时分配给它的任何一个或任何内容。它调用sort
方法 on undefined
。由于undefined
没有sort
方法,它会引发错误。
then
如果您使用 async/await,为什么要打电话?这就是它应该如何实现的 async/await
方式。
async ngOnInit(): Promise<void> {
this.currencyList = await this.dataProviderService.getCurrencyCodesList();
this.currencyList.sort((a, b) => {
return a.code > b.code ? 1 : -1;
});
// ...
}
它基本上等到getCurrencyCodesList()
promise 被解决,然后将响应写入currencyList
字段。然后它继续进行常规同步流程。
由于您使用的是 Promise,因此您的存根应该返回 Promise 而不是 observables。在您的情况下,我会使用 jasmine 间谍而不是存根进行测试,例如:
const localizationProviderSpy = jasmine.createSpyObj<LocalizationProviderService>('LocalizationProviderService', ['getCurrencyCodesList']);
将 spy 添加到您的提供程序列表中,您最有可能使用 TestBed,然后在您的测试用例中使用它,如下所示:
it('should have currencies in the list', async () => {
const expected = [{code: 'PLN', table: 'A'}, {code: 'EUR', table: 'A'}];
localizationProviderSpy
.getCurrencyCodesList
.and
.returnValue(Promise.resolve(expected));
await component.ngOnInit();
expect(component.currencyList.length).toBeGreaterThan(1);
expect(component.currencyList).toEqual(expected);
});
推荐阅读
- javascript - 替代 getState 用于 Redux 中的重复变量
- ag-grid-angular - Ag-grid Angular:自定义标头未检测到触摸
- android - 从构建文件夹安装apk时阻止播放保护但从android studio运行时工作正常
- jsonschema - json 的值有多种数据类型(json-shema)
- python - 具有多个导入的 Python 模块全局变量
- powerbi - 在 dax 命令中使用求和
- python - 在 matplotlib 中固定轴
- python - 如何在我的 python (pandas) Dataframe 中获取一列以查看导致我得到结果的决策树的所有规则?
- puppet - 如何为自定义事实添加依赖项 -Facts['name'] 在所有 exec 命令之前首先执行
- java - 如何在使用 getElementById 运行 JavascriptExecutor 时使用动态的 ID 字段