如何使用 Angular 和 Jest 测试服务中的 http 请求功能

How to test a http request function in a service with Angular and Jest

我创建了一个返回 json 对象的简单服务。


  getCountries() {
    return this.httpService.get('../../assets/countries.json');
  }

测试

describe('TestServiceService', () => {
  let service: TestServiceService;
  let httpController: HttpTestingController;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule]
    });
    httpController = TestBed.inject(HttpTestingController);
    service = TestBed.inject(TestServiceService);
  });

  it('return countries', () => {
    service.getCountries().subscribe(resp => {
      expect(resp).toEqual({'test': 0});
    });
    const req = httpController.expectOne({
      method: 'GET',
      url: '../../assets/countries.json'
    });
    req.flush({'test': 1});
    httpController.verify();
  });
});

当我尝试测试它时,它使用 Jasmine 运行良好,但在将 Jest 设置为测试运行器后,测试总是正常通过,尽管它们并不正常。 当我使用 Jest Runner 插件在 VS Code 中调试测试时,它检测到错误,但 运行 测试以正常方式通过,正常。

更新:

按照 temp_user 的建议使用回调 'done' 我收到超时错误。我可以修复它,设置更长的超时时间,比如 20 秒或更长时间。但我不知道,我认为对于这么简单的测试来说,这太过分了吧?

    thrown: "Exceeded timeout of 5000 ms for a test.
    Use jest.setTimeout(newTimeout) to increase the timeout value, if this is a long-running test."

      19 |   });
      20 |
    > 21 |   it('return countries', (done) => {
         |   ^
      22 |     service.getCountries().subscribe(resp => {
      23 |       expect(resp).toEqual({'test': 0});
      24 |       done();

有什么建议吗?还有其他正确的方法吗? 谢谢

那是因为你是 运行 异步代码,而 Jasmine 并不是开箱即用的。

  it('return countries', (done) => { // Add a callback here
    service.getCountries().subscribe(resp => {
      expect(resp).toEqual({'test': 0});
      done(); // Call the callback here
    });
    const req = httpController.expectOne({
      method: 'GET',
      url: '../../assets/countries.json'
    });
    req.flush({'test': 1});
    httpController.verify();
  });

您可以将 observable 转换为 promise 并应用 fakeAsync/tick 来完成待处理的任务

it('return countries', fakeAsync(() => {
...
service.getCountries().subscribe.toPromise().then(resp => {
...
})
...
req.flush({'test': 1});
httpController.verify();
tick();