Angular 使用参数 return 模拟的可观察对象测试服务
Angular testing Service with params return an mocked observable
我对所有不同类型的单元测试还是陌生的,而且我又一次被困在服务测试中。
这是我要测试的服务中的功能:
For your information:
this.setParams returns an object like {name: 'Test', id: 3}
getDataCount(dataparams: Filter): Observable<number> {
const url = 'http://blablabla.com';
const params = this.setParams(dataparams);
return new Observable<number>(observer => {
this.httpc.get<number>(url, { params }).subscribe(
(data) => {
observer.next(data);
observer.complete();
}
);
}
);
}
我的测试设置是:
describe('MyDataService', () => {
let service: DataService;
let mockParams: Filter;
let mockCount: number;
mockParams = { name: 'Test', id: 3 };
mockCount = 358;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
HttpClientTestingModule
]
});
service = TestBed.inject(DataService);
});
我的测试是这样的:
it('should return mockCount', async () => {
const test = await service.getOperatingDataCount(mockParams).toPromise();
expect(test).toBe(mockCount);
});
但它正在返回 'Async function did not complete within 5000ms (set by jasmine.DEFAULT_TIMEOUT_INTERVAL)'。我也阅读了其他线程,但我仍然无法弄清楚如何为此编写适当的测试。谁能指出我正确的方向?
您应该 await
调用 req.flush()
后的承诺。它将用模拟数据响应,导致 this.httpc.get()
Observable 解析。
只有当您的可观察对象发出一个值时,您的承诺才能被解决或拒绝。
因此,在你调用req.flush()
之前,promise无法被resolve和rejected,导致超时错误。
这是一个使用 "@angular/core": "~11.0.3"
的工作示例
data.service.ts
:
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
export type Filter = any;
@Injectable()
export class DataService {
constructor(private httpc: HttpClient) {}
setParams(dataparams: Filter) {
return dataparams;
}
getDataCount(dataparams: Filter): Observable<number> {
const url = 'http://blablabla.com';
const params = this.setParams(dataparams);
return new Observable<number>((observer) => {
this.httpc
.get<number>(url, { params })
.subscribe((data) => {
console.log(data);
observer.next(data);
observer.complete();
});
});
}
}
data.service.spec.ts
:
import { TestBed } from '@angular/core/testing';
import { DataService, Filter } from './data.service';
import {
HttpClientTestingModule,
HttpTestingController,
} from '@angular/common/http/testing';
fdescribe('MyDataService', () => {
let dataService: DataService;
let mockParams: Filter;
let mockCount: number;
let httpTestingController: HttpTestingController;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [DataService],
});
dataService = TestBed.inject(DataService);
httpTestingController = TestBed.inject(HttpTestingController);
});
it('should get data', async () => {
mockParams = { name: 'Test', id: 3 };
mockCount = 358;
const promise = dataService.getDataCount(mockParams).toPromise();
const req = httpTestingController.expectOne(
'http://blablabla.com?name=Test&id=3'
);
expect(req.request.method).toEqual('GET');
req.flush(mockCount);
const actual = await promise;
expect(actual).toBe(358);
httpTestingController.verify();
});
});
单元测试结果:
我对所有不同类型的单元测试还是陌生的,而且我又一次被困在服务测试中。
这是我要测试的服务中的功能:
For your information:
this.setParams returns an object like {name: 'Test', id: 3}
getDataCount(dataparams: Filter): Observable<number> {
const url = 'http://blablabla.com';
const params = this.setParams(dataparams);
return new Observable<number>(observer => {
this.httpc.get<number>(url, { params }).subscribe(
(data) => {
observer.next(data);
observer.complete();
}
);
}
);
}
我的测试设置是:
describe('MyDataService', () => {
let service: DataService;
let mockParams: Filter;
let mockCount: number;
mockParams = { name: 'Test', id: 3 };
mockCount = 358;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
HttpClientTestingModule
]
});
service = TestBed.inject(DataService);
});
我的测试是这样的:
it('should return mockCount', async () => {
const test = await service.getOperatingDataCount(mockParams).toPromise();
expect(test).toBe(mockCount);
});
但它正在返回 'Async function did not complete within 5000ms (set by jasmine.DEFAULT_TIMEOUT_INTERVAL)'。我也阅读了其他线程,但我仍然无法弄清楚如何为此编写适当的测试。谁能指出我正确的方向?
您应该 await
调用 req.flush()
后的承诺。它将用模拟数据响应,导致 this.httpc.get()
Observable 解析。
只有当您的可观察对象发出一个值时,您的承诺才能被解决或拒绝。
因此,在你调用req.flush()
之前,promise无法被resolve和rejected,导致超时错误。
这是一个使用 "@angular/core": "~11.0.3"
data.service.ts
:
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
export type Filter = any;
@Injectable()
export class DataService {
constructor(private httpc: HttpClient) {}
setParams(dataparams: Filter) {
return dataparams;
}
getDataCount(dataparams: Filter): Observable<number> {
const url = 'http://blablabla.com';
const params = this.setParams(dataparams);
return new Observable<number>((observer) => {
this.httpc
.get<number>(url, { params })
.subscribe((data) => {
console.log(data);
observer.next(data);
observer.complete();
});
});
}
}
data.service.spec.ts
:
import { TestBed } from '@angular/core/testing';
import { DataService, Filter } from './data.service';
import {
HttpClientTestingModule,
HttpTestingController,
} from '@angular/common/http/testing';
fdescribe('MyDataService', () => {
let dataService: DataService;
let mockParams: Filter;
let mockCount: number;
let httpTestingController: HttpTestingController;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [DataService],
});
dataService = TestBed.inject(DataService);
httpTestingController = TestBed.inject(HttpTestingController);
});
it('should get data', async () => {
mockParams = { name: 'Test', id: 3 };
mockCount = 358;
const promise = dataService.getDataCount(mockParams).toPromise();
const req = httpTestingController.expectOne(
'http://blablabla.com?name=Test&id=3'
);
expect(req.request.method).toEqual('GET');
req.flush(mockCount);
const actual = await promise;
expect(actual).toBe(358);
httpTestingController.verify();
});
});
单元测试结果: