Max Kurtz
Max Kurtz

Reputation: 478

Mocking timers in pRetry function for testing purpose

I'd like to test a function which uses pRetry npm package with Jest testing framework. I want to speed up tests flow, thus I don't want to wait until pRetry actual timers trigger. To simplify the task, I'd like to have my test run less than 500 ms, and console.log message in // *** line is printed 7 (or 8?) times. I've tried using jest.useFakeTimers, jest.runAllTimers and others with no success. Please, help, I stuck :)

my function looks like:

myFunc() {
  return pRetry(async () => {
    if(Math.random() > 0.5){
      return true;
    }

    console.log(`currentTime: ${Date.now()}`); // ***

    throw new Error('Calculations failed....');
  }, {
    retries: 7,
    minTimeout: 500,
  });
}

my test looks like:

 it('should throw an error if calculations failed', async () => {
      await myFunc();

      expect(true).toBeTruthy();
    });

Upvotes: 0

Views: 515

Answers (2)

Ilshidur
Ilshidur

Reputation: 1521

I managed to (very simply) mock p-retry using Jest :

jest.mock('p-retry', () => async (fn) => {
  const tryFn = async (attemptCount) => {
    try {
      return await fn(attemptCount)
    } catch (error) {
      await new Promise((resolve) => setTimeout(resolve, 1))
      return tryFn(attemptCount + 1)
    }
  }

  return tryFn(0)
})

Upvotes: 1

plop
plop

Reputation: 366

Needed this but could not find a way neither.

I ended up making the minTimeout of pRetry get its value from a function which I stub during testing (and so I export)

something like that:

// used to be overwritten by testing
export const getMinTimeout = () => 1000;
  await pRetry(
    async () => {
      return doRetry();
    },
    {
      minTimeout: exports.getMinTimeout(),
     
    }
      sandbox.stub(ApiV2, 'getMinTimeout').returns(10);

this works well

Upvotes: 1

Related Questions