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() 上,测试将失败,因为该服务正在进行两次调用,而测试预计只有一次调用。