0
0
JavascriptHow-ToBeginner · 3 min read

How to Test Async Code in JavaScript: Simple Guide

To test async code in JavaScript, use async/await or return a Promise in your test function so the test runner knows to wait. Testing frameworks like Jest support this by allowing tests to be declared async or by returning promises.
📐

Syntax

Testing async code usually involves one of these patterns:

  • Async/Await: Mark the test function as async and use await inside it.
  • Returning a Promise: Return a Promise from the test function so the test runner waits for it.
  • Callback with done: Use a done callback parameter and call it when async work finishes (less common now).
javascript
test('async test with async/await', async () => {
  const data = await fetchData();
  expect(data).toBe('hello');
});

// Or returning a Promise

test('async test returning promise', () => {
  return fetchData().then(data => {
    expect(data).toBe('hello');
  });
});

// Using done callback (legacy)

test('async test with done callback', done => {
  fetchData().then(data => {
    expect(data).toBe('hello');
    done();
  });
});
💻

Example

This example shows how to test an async function that returns a promise using async/await in Jest. It waits for the async function to complete and checks the result.

javascript
function fetchData() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('hello');
    }, 100);
  });
}

test('fetchData returns hello', async () => {
  const result = await fetchData();
  expect(result).toBe('hello');
});
Output
PASS fetchData returns hello
⚠️

Common Pitfalls

Common mistakes when testing async code include:

  • Not returning the promise or not using async in the test, causing the test to finish before the async code runs.
  • Forgetting to call done() when using the callback style, which makes tests hang or timeout.
  • Mixing callback and promise styles incorrectly.
javascript
/* Wrong: test finishes before async code runs */
test('wrong async test', () => {
  fetchData().then(data => {
    expect(data).toBe('hello');
  });
});

/* Right: return the promise or use async/await */
test('right async test', () => {
  return fetchData().then(data => {
    expect(data).toBe('hello');
  });
});

// Or

test('right async test with async/await', async () => {
  const data = await fetchData();
  expect(data).toBe('hello');
});
📊

Quick Reference

Summary tips for testing async code:

  • Use async/await for clear and readable tests.
  • Always return a Promise or mark the test async so the test runner waits.
  • Avoid mixing callback done style with promises unless necessary.
  • Use try/catch inside async tests to handle errors gracefully.

Key Takeaways

Mark test functions as async or return a Promise to properly test async code.
Use async/await for simpler and more readable async tests.
Avoid forgetting to return promises or call done(), which causes false positives or hanging tests.
Handle errors inside async tests with try/catch to avoid unhandled rejections.
Prefer modern async/await style over callback done() style for clarity.