HttpTestingController 因无法匹配条件而失败
HttpTestingController fails with Failed to Match Criteria
我创建了一个将用户保存到数据库的 UserService。我还有一个预配置端点的服务,用于本地、qa、uat 和 prod,称为 UrlService。 class returns 承诺使用 APP_INITIALIZER 的 URls,效果很好。资产文件夹 urls.json 中的配置似乎干扰了测试。当我在 matches 方法中添加一个 console.log 时,它会打印出 /asset/urls.json 中的路径。我不明白这会如何干扰我的测试。我很困惑这会对我的测试产生任何影响,但任何见解都会有所帮助。
当我 运行 我的测试失败并显示错误:
Error: Expected one matching request for criteria "Match by function: ", found 2 requests. I print out the URL and it matches what gets printed in the service and it matches the one in the test.
网址不匹配怎么办?我对此完全困惑?
有人知道这是怎么回事吗?
export class UserDetail{
name: string;
department: string;
userId: string;
}
saveUser(
user: UserDetail,
url: string
): Observable<UserDetail> {
return this.http
.post<UserDetail>(
url,
user,
this.httpOptions
)
.pipe(
tap(
(resp: UserDetail) =>
console.log(`New User ${user}`),
(error) => {
console.log('Received an error', error);
}
)
);
console.log('URL passed is ', url);
}
it("Create User", fakeAsync(() => {
user = {
name: "Ranger",
department: "Merch",
userId: "1222222",
};
let response = null;
const URL = urlService.getConfig().userLocal;
userService.saveUser(user, URL).subscribe(
(expectedResponse) => {
response = expectedResponse;
},
(error: any) => {}
);
const req = httpMock.expectOne((request) => {
console.log("URL is: ", request.url);
return true;
});
const requestWrapper = httpMock.expectOne({
url: URL,
});
requestWrapper.flush(user);
tick();
expect(requestWrapper.request).toBeTruthy();
expect(requestWrapper.request.method).toEqual("POST");
expect(response.request).toBeTruthy();
}));
问题是 httpMock
被触发了两次,所以当您 expectOne
它失败并抛出您显示的错误消息:... found 2 requests.
.
要解决这个问题,您可以定义预期的请求,类似于:
httpMock.expectOne((request) =>
return request.method === 'POST' && request.url === URL;
);
编辑:
让我进一步解释一下,如果您使用 HttpClient 进行两次调用,并且在您的测试中使用 expectOne,您的测试将失败并显示您收到的错误消息。
查看此服务的示例:
export class DataServiceService {
constructor(private httpClient: HttpClient) { }
testSingleCall() {
return this.httpClient.get('/data').subscribe();
}
testDoubleCalls() {
this.httpClient.get('/data').subscribe();
this.httpClient.get('/data').subscribe();
}
}
这是测试文件:
it('should test httpmock', () => {
service.testSingleCall();
// If no request with that URL was made, or if multiple requests match, expectOne() would throw.
httpMock.expectOne("/data");
});
it('should test httpmock multiple calls', () => {
service.testDoubleCalls();
const requests = httpMock.match("/data");
expect(requests.length).toEqual(2);
});
如果您 运行 httpMock.expectOne("/data")
在 testDoubleCalls()
上,测试将失败,因为该服务正在进行两次调用,而测试预计只有一次调用。
我创建了一个将用户保存到数据库的 UserService。我还有一个预配置端点的服务,用于本地、qa、uat 和 prod,称为 UrlService。 class returns 承诺使用 APP_INITIALIZER 的 URls,效果很好。资产文件夹 urls.json 中的配置似乎干扰了测试。当我在 matches 方法中添加一个 console.log 时,它会打印出 /asset/urls.json 中的路径。我不明白这会如何干扰我的测试。我很困惑这会对我的测试产生任何影响,但任何见解都会有所帮助。
当我 运行 我的测试失败并显示错误:
Error: Expected one matching request for criteria "Match by function: ", found 2 requests. I print out the URL and it matches what gets printed in the service and it matches the one in the test.
网址不匹配怎么办?我对此完全困惑? 有人知道这是怎么回事吗?
export class UserDetail{
name: string;
department: string;
userId: string;
}
saveUser(
user: UserDetail,
url: string
): Observable<UserDetail> {
return this.http
.post<UserDetail>(
url,
user,
this.httpOptions
)
.pipe(
tap(
(resp: UserDetail) =>
console.log(`New User ${user}`),
(error) => {
console.log('Received an error', error);
}
)
);
console.log('URL passed is ', url);
}
it("Create User", fakeAsync(() => {
user = {
name: "Ranger",
department: "Merch",
userId: "1222222",
};
let response = null;
const URL = urlService.getConfig().userLocal;
userService.saveUser(user, URL).subscribe(
(expectedResponse) => {
response = expectedResponse;
},
(error: any) => {}
);
const req = httpMock.expectOne((request) => {
console.log("URL is: ", request.url);
return true;
});
const requestWrapper = httpMock.expectOne({
url: URL,
});
requestWrapper.flush(user);
tick();
expect(requestWrapper.request).toBeTruthy();
expect(requestWrapper.request.method).toEqual("POST");
expect(response.request).toBeTruthy();
}));
问题是 httpMock
被触发了两次,所以当您 expectOne
它失败并抛出您显示的错误消息:... found 2 requests.
.
要解决这个问题,您可以定义预期的请求,类似于:
httpMock.expectOne((request) =>
return request.method === 'POST' && request.url === URL;
);
编辑: 让我进一步解释一下,如果您使用 HttpClient 进行两次调用,并且在您的测试中使用 expectOne,您的测试将失败并显示您收到的错误消息。
查看此服务的示例:
export class DataServiceService {
constructor(private httpClient: HttpClient) { }
testSingleCall() {
return this.httpClient.get('/data').subscribe();
}
testDoubleCalls() {
this.httpClient.get('/data').subscribe();
this.httpClient.get('/data').subscribe();
}
}
这是测试文件:
it('should test httpmock', () => {
service.testSingleCall();
// If no request with that URL was made, or if multiple requests match, expectOne() would throw.
httpMock.expectOne("/data");
});
it('should test httpmock multiple calls', () => {
service.testDoubleCalls();
const requests = httpMock.match("/data");
expect(requests.length).toEqual(2);
});
如果您 运行 httpMock.expectOne("/data")
在 testDoubleCalls()
上,测试将失败,因为该服务正在进行两次调用,而测试预计只有一次调用。