Jest
Testing
Promises
setTimeout
JavaScript

Testing a Promise using setTimeout with Jest

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Testing a Promise with setTimeout using Jest

JavaScript promises and asynchronous code can sometimes be challenging to test, especially when using libraries like Jest. One common scenario is testing a promise that relies on setTimeout. Below, we'll explore how to test such a promise, explain the required concepts, and provide illustrative examples with Jest.

Understanding Promises and setTimeout

Promises in JavaScript allow us to work with asynchronous operations in a more manageable way. A promise has three states: pending, fulfilled, and rejected. It provides a way to associate handlers with an asynchronous action's eventual success value or failure reason.

setTimeout, on the other hand, is a JavaScript function that executes a given function after a specified number of milliseconds. When we combine a promise with setTimeout, we usually set a delay before the promise is resolved or rejected. Here's a simple function that returns a promise using setTimeout:

javascript
1function delayedPromise(ms) {
2  return new Promise((resolve) => {
3    setTimeout(() => {
4      resolve('Promise Resolved after ' + ms + 'ms');
5    }, ms);
6  });
7}

Testing using Jest

Jest is a popular testing framework for JavaScript applications. It offers powerful features for mocking, asserting, and organizing tests.

To test the delayedPromise function, we need to ensure that Jest handles the asynchronous nature of the promise and the delay introduced by setTimeout.

Here's how you can structure your test:

  1. Using done Callback
    Jest provides a done callback to signal that asynchronous setup is complete. Call the done function when you're done with a test that involves asynchronous code:
javascript
1   test('delayedPromise resolves', (done) => {
2     delayedPromise(500).then((data) => {
3       expect(data).toBe('Promise Resolved after 500ms');
4       done();
5     });
6   });
  1. Using return with Promises
    You can return a promise from the test function, and Jest will wait for that promise to resolve:
javascript
1   test('delayedPromise resolves', () => {
2     return delayedPromise(500).then((data) => {
3       expect(data).toBe('Promise Resolved after 500ms');
4     });
5   });
  1. Using the async/await Syntax
    By using async and await, you can write more concise tests that handle asynchronous code:
javascript
1   test('delayedPromise resolves', async () => {
2     const data = await delayedPromise(500);
3     expect(data).toBe('Promise Resolved after 500ms');
4   });

Mocking setTimeout

When testing, it's often useful to mock setTimeout to control the passage of time. Jest provides functions like jest.useFakeTimers() and jest.advanceTimersByTime() to simulate and manipulate the timer functions for testing.

Here's how to mock setTimeout in your tests:

javascript
1test('delayedPromise resolves with mocked setTimeout', () => {
2  jest.useFakeTimers();
3
4  const promise = delayedPromise(500);
5
6  jest.advanceTimersByTime(500);
7
8  return promise.then((data) => {
9    expect(data).toBe('Promise Resolved after 500ms');
10  });
11});

In this example, jest.useFakeTimers() replaces the real timer functions with mocked versions. We can then use jest.advanceTimersByTime(500) to simulate the passage of time, allowing us to test the promise without actually waiting.

Key Points

The following table summarizes key methods and concepts when testing promises using setTimeout in Jest:

FeatureDescription
done callbackSignals the completion of an asynchronous test.
Return promiseReturn a promise from the test function for Jest to wait on it automatically.
async/awaitUse async/await for more readable asynchronous test syntax.
jest.useFakeTimers()Replace real timers with mocked versions for testing.
jest.advanceTimersByTime(ms)Simulate the passage of time by advancing mocked timers by the specified ms.

Conclusion

Testing promises that involve setTimeout using Jest is straightforward once you grasp the asynchronous nature of JavaScript. By leveraging callbacks, promise returns, and the async/await syntax, your tests can be both comprehensive and maintainable. Additionally, Jest's timer mocks let you control and manipulate time effectively, making your test suite even faster and more reliable.


Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.