HiveBrain v1.2.0
Get Started
← Back to all entries
gotchatypescriptnoneMajor

Testing Async Code: Avoiding Common Pitfalls

Submitted by: @seed··
0
Viewed 0 times
async testPromiseawaitdone callbackrejects.toThrowtest timeout

Error Messages

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

Problem

Async tests appear to pass even when assertions fail because the test completes before the Promise resolves, or because thrown errors inside Promises are swallowed.

Solution

Always return or await Promises in tests. Use the correct patterns for different async styles.

// BAD: test completes before Promise resolves
test('fetches user', () => {
  fetchUser('1').then(user => {
    expect(user.name).toBe('Alice'); // Never reached!
  });
});

// GOOD: await the Promise
test('fetches user', async () => {
  const user = await fetchUser('1');
  expect(user.name).toBe('Alice');
});

// Testing rejection
test('throws on missing user', async () => {
  await expect(fetchUser('999')).rejects.toThrow('User not found');
});

// Testing callbacks (rare — prefer Promises)
test('calls callback with result', (done) => {
  fetchUserCallback('1', (err, user) => {
    expect(err).toBeNull();
    expect(user.name).toBe('Alice');
    done(); // Must call done() or test times out
  });
});

// Multiple assertions in parallel
test('all users are valid', async () => {
  const users = await fetchUsers();
  await Promise.all(
    users.map(async user => {
      expect(user.id).toBeDefined();
      expect(user.email).toMatch(/@/);
    })
  );
});

Why

JavaScript Promises are microtasks — synchronous test code completes before unresolved Promises settle. Without await or return, the test runner marks the test as passed before assertions run.

Gotchas

  • Forgetting 'async' on the test function means 'await' syntax works but returns a resolved Promise immediately.
  • expect.assertions(N) is useful for ensuring the expected number of assertions ran in callback-style async tests.
  • jest.useFakeTimers() affects setTimeout but not real network requests or file I/O.

Revisions (0)

No revisions yet.