angular - Angular http get response in observable 在单元测试中不是类型转换
问题描述
我正在尝试学习角度内置单元测试。
我有使用 http.get 进入映射的方法的服务,并返回类型化的可观察流 (Observable<BankAccountFull[]>)。
但是,当我尝试使用 angular.io“测试服务”页面中的逻辑对其进行测试时,我不断收到错误消息Expected $[0] to be a kind of BankAccountFull, but was Object({...
。
尝试在测试的箭头函数参数和期望内部进行类型转换。
服务代码:
import { Injectable } from '@angular/core';
import { catchError, map } from 'rxjs/operators';
import { HttpClient } from '@angular/common/http';
import { BankAccountFull } from '../types/bank-account';
import { Observable, of } from 'rxjs';
import { ACCOUNTTYPES, AccountType } from '../types/account-type';
import { TankType, TANKTYPES } from '../types/tank-type';
import { AccList } from '../types/acc-list';
@Injectable({
providedIn: 'root'
})
export class BankAccountService {
private accountsUrl = 'api/accounts';
constructor(private http: HttpClient) { }
getAccountList(token: string): Observable<BankAccountFull[]> {
return this.http.get<BankAccountFull[]>(this.accountsUrl)
.pipe(
map(response => {
const accounts: BankAccountFull[] = response as BankAccountFull[];
return accounts.map((item) => {
const temp: AccountType = ACCOUNTTYPES.find(el => el.id === item.accType);
const tempRes: BankAccountFull = {...item};
if (temp.id) {
tempRes.accTypeHint = temp.hint;
tempRes.accTypeImg = temp.img;
}
const tempTank: TankType = TANKTYPES.find(el => el.id === item.tankType);
if (tempTank.id) {
tempRes.tankTypeImg = tempTank.img;
tempRes.tankTypeName = tempTank.name;
}
return tempRes;
}
);
}),
catchError(this.handleError<BankAccountFull[]>('getHeroes', []))
);
}
private handleError<T>(operation = 'operation', result?: T): (error: any) => Observable<T> {
return (error: any): Observable<T> => {
console.error(error);
return of(result as T);
};
}
}
单元测试代码:
import { BankAccountService } from './bank-account.service';
import { BankAccountFull } from '../types/bank-account';
import { of } from 'rxjs';
import { HttpClient } from '@angular/common/http';
describe('BankAccountService', () => {
let httpClientSpy: {get: jasmine.Spy};
let service: BankAccountService;
beforeEach(() => {
httpClientSpy = jasmine.createSpyObj('HttpClient', ['get']);
service = new BankAccountService(httpClientSpy as any);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
it('should return expected accounts list', () => {
const expectedAccList: BankAccountFull[] =
[
new BankAccountFull(true, 1, '068985 2563', 1, 500000, 0,
'../../assets/img/acc-types/mortgage.png', 'Mortgage', '../../assets/img/tank-types/property-tank.png', 'Property Tank'),
new BankAccountFull(false, 2, '068985 2563', 1, 500000, 0, '../../assets/img/acc-types/mortgage.png', 'Mortgage',
'../../assets/img/tank-types/property-tank.png', 'Property Tank'),
new BankAccountFull(false, 3, '068985 2563', 2, 50000, 1, '../../assets/img/acc-types/car-loan.png', 'Car loan',
'../../assets/img/tank-types/property-tank.png', 'Work Tank'),
new BankAccountFull(false, 4, '068985 2563', 3, 50000, 1, '../../assets/img/acc-types/personal-loan.png', 'Personal credit',
'../../assets/img/tank-types/property-tank.png', 'Work Tank'),
];
httpClientSpy.get.and.returnValue(of(expectedAccList));
service.getAccountList('someMD5Token').subscribe(
(accList: BankAccountFull[]) => expect(accList as BankAccountFull[]).toEqual(expectedAccList, 'expected accounts list'),
fail
);
});
});
测试总结:
BankAccountService > should return expected accounts list
Expected $[0] to be a kind of BankAccountFull, but was Object({ active: true, id: 1, name: '068985 2563', accType: 1, balance: 500000, tankType: 0, accTypeImg: '../../assets/img/acc-types/mortgage.png', accTypeHint: 'Mortgage', tankTypeImg: '../../assets/img/tank-types/property-tank.png', tankTypeName: 'Property Tank' }).
Expected $[1] to be a kind of BankAccountFull, but was Object({ active: false, id: 2, name: '068985 2563', accType: 1, balance: 500000, tankType: 0, accTypeImg: '../../assets/img/acc-types/mortgage.png', accTypeHint: 'Mortgage', tankTypeImg: '../../assets/img/tank-types/property-tank.png', tankTypeName: 'Property Tank' }).
Expected $[2] to be a kind of BankAccountFull, but was Object({ active: false, id: 3, name: '068985 2563', accType: 2, balance: 50000, tankType: 1, accTypeImg: '../../assets/img/acc-types/car-loan.png', accTypeHint: 'Car loan', tankTypeImg: '../../assets/img/tank-types/property-tank.png', tankTypeName: 'Work Tank' }).
Expected $[3] to be a kind of BankAccountFull, but was Object({ active: false, id: 4, name: '068985 2563', accType: 3, balance: 50000, tankType: 1, accTypeImg: '../../assets/img/acc-types/personal-loan.png', accTypeHint: 'Personal credit', tankTypeImg: '../../assets/img/tank-types/property-tank.png', tankTypeName: 'Work Tank' }).
解决方案
您应该使用HttpTestingController
Http Requests 进行单元测试,它有更好的 API ( https://medium.com/better-programming/testing-http-requests-in-angular-with-httpclienttestingmodule-3880ceac74cf )。
至于您为什么会看到该错误,我怀疑该行将const tempRes: BankAccountFull = {...item};
类型更改为tempRes
to Object
。这是一本很好的读物,我认为您面临着类似的情况:https ://ultimatecourses.com/blog/ngrx-store-testing-actions ( Expected object to be a kind of Object, but was LoadPizzas
.)
推荐阅读
- java - 在 Flutter 模块中获取参数
- flutter - 如何检测颤振应用程序中的硬件按钮(物理设备)?
- xamarin - Tizen Xamarin 可穿戴 CircleProgressBarSurfaceItem 在 CarouselPage
- android - 如何从片段中的 Activity 访问按钮?
- html - 为什么“URL:https://www.google.com/”的超链接仅在 W3Schools 的“自己尝试”编辑器中不起作用?
- c# - EF Core 5.0 添加多对多使得一对多无法确定
- email - 根据单元格值发送电子邮件
- algorithm - 创建“Spot It”/“Dobble”卡片的算法,但具有来自任意两张卡片的两个常见图像
- java - 重复 Maven settings.xml 的目的
- swift - 为什么这个 Swift Timer 没有触发?