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

Time:05-25

I created a simple service returning a json object.


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

The test

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();
  });
});

When I try to test it, it worked fine using Jasmine, but after setting Jest as test runner, the test always pass as ok, althought they aren't ok. When I debug the test in VS Code with the Jest Runner plugin it detects the error, but running the test in a normal way it passes as ok.

UPDATE:

Using the callback 'done' as temp_user suggested I get a timeout error. I can fix it setting a longer timeout, like 20 seconds or more. But I don't know, I think that's excesive for such a simple test, right?

    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();

Any suggestions? Is there any other proper way to do it? Thank you

CodePudding user response:

That's because you are running asynchronous code, and Jasmine isn't made to do that out of the box.

  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();
  });

CodePudding user response:

You may convert the observable to a promise and apply fakeAsync/tick to complete the pending tasks

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