使用 Jamine 测试基于 HTTP 的异步函数:超时 - 未在 5000 毫秒内调用异步回调
Testing async HTTP-based function with Jamine: Timeout - Async callback was not invoked within 5000ms
内容:测试返回依赖于嵌套 http 调用的 Promise 的异步函数
搭配:Angular9,茉莉花 3.4.0
问题:错误:超时 - 在 5000 毫秒(由 jasmine.DEFAULT_TIMEOUT_INTERVAL 设置)内未调用异步回调
错误:预期没有打开请求,发现 1:GET http://localhost:9876/24a27be6-9f62-4156-8fd4-adcd945ec909
import ...
export interface UserData {...}
@Injectable()
export class UserDataManagementService {
private userID: string | undefined;
public userData: UserData;
constructor(...) {}
private async loadUserData() {
const headers = await this.getHeaders();
return this.httpClient
.get<UserData>(window.location.origin + '/' + this.userID, { headers })
.toPromise()
.then((data) => {
this.userData = data;
})
.catch((e) => {
this.logger.error('Error in loadUserData: ', e);
});
}
private async getHeaders() {...}
}
这是我的测试:
import ...
const mockUserData: UserData = {...};
describe('UserDataManagementService', () => {
let httpTestingController: HttpTestingController;
let service: UserDataManagementService;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [
UserDataManagementService,
...
],
});
httpTestingController = TestBed.get(HttpTestingController);
service = TestBed.get(UserDataManagementService);
});
afterEach(() => {
httpTestingController.verify();
});
describe('loadUserData', () => {
it('should return user data on success', (done) => {
(service as any).userID = '24a27be6-9f62-4156-8fd4-adcd945ec909';
(service as any).loadUserData().then(() => {
expect((service as any).userData).toEqual(mockUserData);
const req = httpTestingController.expectOne(
'http://localhost:9876/24a27be6-9f62-4156-8fd4-adcd945ec909',
);
expect(req.request.method).toEqual('GET');
req.flush(mockUserData);
done();
});
});
});
});
到目前为止我尝试了什么:
- 尝试将默认超时增加到 20000 毫秒 - 没有成功
- 完成/异步/等待等的不同组合
- 在 then() 之外放置 httpTestingController.expectOne(没有真正意义,但我已经尝试了所有方法)
- 如果我将 httpTestingController.verify() 放入此测试中,错误 "expected no open requests..." 就会消失
这不是以下内容的重复:
- 我的功能returns一个承诺,比如
- 我使用 done(),比如
- 我没有像here
这样的长期运行任务
- fakeAsync 对我也没有帮助...
虽然我无法重现您的测试环境,但您的测试似乎超时了,因为您的模拟请求从未得到满足。它从未实现的原因是因为您在旨在处理响应的回调中刷新了测试请求。
(service as any).loadUserData().then(() => {
const req = httpTestingController.expectOne(
'http://localhost:9876/24a27be6-9f62-4156-8fd4-adcd945ec909',
);
expect((service as any).userData).toEqual(mockUserData);
expect(getHeadersSpy).toHaveBeenCalled();
expect(req.request.method).toEqual('GET');
// this line tells the test scaffolding to fulfill the request
req.flush(mockUserData);
done();
});
我希望如果您重构以刷新请求,那么您的测试将不会超时(可能仍会因其他原因而失败)。
const req = httpTestingController.expectOne('http://localhost:9876/24a27be6-9f62-4156-8fd4-adcd945ec909');
(service as any).loadUserData().then(() => {
expect((service as any).userData).toEqual(mockUserData);
expect(getHeadersSpy).toHaveBeenCalled();
expect(req.request.method).toEqual('GET');
done();
});
req.flush(mockUserData); // <= essentially: 'call my callback now!'
内容:测试返回依赖于嵌套 http 调用的 Promise 的异步函数
搭配:Angular9,茉莉花 3.4.0
问题:错误:超时 - 在 5000 毫秒(由 jasmine.DEFAULT_TIMEOUT_INTERVAL 设置)内未调用异步回调 错误:预期没有打开请求,发现 1:GET http://localhost:9876/24a27be6-9f62-4156-8fd4-adcd945ec909
import ...
export interface UserData {...}
@Injectable()
export class UserDataManagementService {
private userID: string | undefined;
public userData: UserData;
constructor(...) {}
private async loadUserData() {
const headers = await this.getHeaders();
return this.httpClient
.get<UserData>(window.location.origin + '/' + this.userID, { headers })
.toPromise()
.then((data) => {
this.userData = data;
})
.catch((e) => {
this.logger.error('Error in loadUserData: ', e);
});
}
private async getHeaders() {...}
}
这是我的测试:
import ...
const mockUserData: UserData = {...};
describe('UserDataManagementService', () => {
let httpTestingController: HttpTestingController;
let service: UserDataManagementService;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [
UserDataManagementService,
...
],
});
httpTestingController = TestBed.get(HttpTestingController);
service = TestBed.get(UserDataManagementService);
});
afterEach(() => {
httpTestingController.verify();
});
describe('loadUserData', () => {
it('should return user data on success', (done) => {
(service as any).userID = '24a27be6-9f62-4156-8fd4-adcd945ec909';
(service as any).loadUserData().then(() => {
expect((service as any).userData).toEqual(mockUserData);
const req = httpTestingController.expectOne(
'http://localhost:9876/24a27be6-9f62-4156-8fd4-adcd945ec909',
);
expect(req.request.method).toEqual('GET');
req.flush(mockUserData);
done();
});
});
});
});
到目前为止我尝试了什么:
- 尝试将默认超时增加到 20000 毫秒 - 没有成功
- 完成/异步/等待等的不同组合
- 在 then() 之外放置 httpTestingController.expectOne(没有真正意义,但我已经尝试了所有方法)
- 如果我将 httpTestingController.verify() 放入此测试中,错误 "expected no open requests..." 就会消失
这不是以下内容的重复:
- 我的功能returns一个承诺,比如
- 我使用 done(),比如
- 我没有像here 这样的长期运行任务
- fakeAsync 对我也没有帮助...
虽然我无法重现您的测试环境,但您的测试似乎超时了,因为您的模拟请求从未得到满足。它从未实现的原因是因为您在旨在处理响应的回调中刷新了测试请求。
(service as any).loadUserData().then(() => {
const req = httpTestingController.expectOne(
'http://localhost:9876/24a27be6-9f62-4156-8fd4-adcd945ec909',
);
expect((service as any).userData).toEqual(mockUserData);
expect(getHeadersSpy).toHaveBeenCalled();
expect(req.request.method).toEqual('GET');
// this line tells the test scaffolding to fulfill the request
req.flush(mockUserData);
done();
});
我希望如果您重构以刷新请求,那么您的测试将不会超时(可能仍会因其他原因而失败)。
const req = httpTestingController.expectOne('http://localhost:9876/24a27be6-9f62-4156-8fd4-adcd945ec909');
(service as any).loadUserData().then(() => {
expect((service as any).userData).toEqual(mockUserData);
expect(getHeadersSpy).toHaveBeenCalled();
expect(req.request.method).toEqual('GET');
done();
});
req.flush(mockUserData); // <= essentially: 'call my callback now!'