Search code examples
angulartypescriptjestjsangular-test

Jest - Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout.Error


I can see there are lots of questions about this on SO but none of them answer my problem.

I have the following test

 it('will poll until there are no subscribers', () => {
    const polls: string[] = [];
    const complete = new Subject<void>();
    const observableSub = service
      .getPollData()
      .pipe(takeUntil(complete))
      .subscribe((value) => {
        polls.push(value);
        if (polls.length === 3) {
          console.log('here ' + JSON.stringify(polls));
          observableSub.unsubscribe();
          complete.next();
          complete.complete();
        }
      });

    return complete.toPromise().then(() => {
      console.log(service.isPolling);
      expect(service.isPolling).toEqual(false);
    });
  });

When the test runs both of my console logs are present and have the correct expected values. This all happens within 20ms, my poll frequency is set at just 5ms for the test.

I have looked at every SO post I can find, I have tried using async, async(done) => done(), fakeAsync and nothing seems to work. I always get the following error:

Timeout - Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout.Error: Timeout - Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout.

NB : I am injecting a MockInterceptor for the responses and the service is using RxJs timer() observable for the polling, I can confirm that this is closed and unsubscribed at then end of the test, this is confirmed by the expect(service.isPolling) line of code. I have tried using jest.userRealTimers and jest.useFakeTimers in case this was part of the issue, but the fact that my console logs show the expected values makes me think this is not the issue.

Any help would be appreciated.

*Update as suggested by @Estus Flask I have updated the code now to this:

it('will poll until there are no subscribers', async () => {
      const polls: any[] = [];
      const observableSub = service.getPollData().pipe(
      take(3),
      tap((value) => {
        polls.push(value);
      })
    );
      await observableSub.toPromise().then(() => {
      console.log(JSON.stringify(polls));
      console.log(service.isPolling);
      expect(service.isPolling).toEqual(false);
    });
 });

But still getting the same error, feel I am doing/missing something simple and stupid ?!?!? NB: Console outputs are still all correct.


Solution

  • If anyone else comes across this issue, its worth taking a look at your other tests in the test set.

    Turned out that for me the above test was passing fine, however a subsequent test with a setTimeout was failing. This was confusing Jest which was then marking the passing test as failed!

    I lost a LOT of time on this, so hopefully this helps someone in the future.