Chuck's Academy

Testing JavaScript and DOM with Jest

Async Testing with Jest

Async Testing with Jest

Modern applications often rely on asynchronous operations such as HTTP requests, timers, and promises. Testing these behaviors is crucial to ensure your code handles asynchrony properly. In this section, we will learn how to perform asynchronous tests using Jest.

Testing Promises

Jest provides several ways to handle promises and asynchronous tests effectively.

  1. Testing with .then() and catch():
javascript
// fetchData.js
const fetchData = () => {
return new Promise((resolve) => {
setTimeout(() => {
resolve('datos recibidos');
}, 1000);
});
};

module.exports = fetchData;
javascript
// __tests__/fetchData.test.js
const fetchData = require('../fetchData');

test('fetchData returns the appropriate data', () => {
return fetchData().then(data => {
expect(data).toBe('datos recibidos');
});
});
  1. Using async/await:
javascript
test('fetchData returns the appropriate data using async/await', async () => {
const data = await fetchData();
expect(data).toBe('datos recibidos');
});
  1. Handling Rejected Promises:

If you want to test a rejection, you can use expect.assertions to ensure that at least one assertion is called in your tests:

javascript
const fetchDataWithError = () => {
return new Promise((_, reject) => {
setTimeout(() => {
reject(new Error('error'));
}, 1000);
});
};

test('fetchDataWithError handles the error correctly', async () => {
expect.assertions(1);
try {
await fetchDataWithError();
} catch (e) {
expect(e.message).toMatch('error');
}
});

Testing HTTP Calls

Simulating HTTP calls is a common practice in async testing. You can use jest.mock to mock modules like axios or fetch.

  1. Using jest.mock to Mock Modules:
javascript
// api.js
const axios = require('axios');

const getData = async () => {
const response = await axios.get('https://api.example.com/data');
return response.data;
};

module.exports = getData;
javascript
// __tests__/api.test.js
const axios = require('axios');
const getData = require('../api');

jest.mock('axios');

test('getData calls axios and returns data', async () => {
axios.get.mockResolvedValue({ data: 'datos mockeados' });

const data = await getData();
expect(data).toBe('datos mockeados');
expect(axios.get).toHaveBeenCalledWith('https://api.example.com/data');
});

Testing Timers and Asynchronous Functions

Jest allows you to control time in your tests using methods like jest.useFakeTimers() and jest.runAllTimers().

  1. Simulating Timers:
javascript
// timer.js
const timer = (callback) => {
setTimeout(() => {
callback('tiempo cumplido');
}, 1000);
};

module.exports = timer;
javascript
// __tests__/timer.test.js
const timer = require('../timer');

jest.useFakeTimers();

test('timer calls the callback after 1 second', () => {
const callback = jest.fn();
timer(callback);

jest.runAllTimers();

expect(callback).toHaveBeenCalledWith('tiempo cumplido');
expect(callback).toHaveBeenCalledTimes(1);
});

Testing Asynchronous Operations in React

With React components, you can use @testing-library/react along with Jest to test asynchronous effects.

  1. Simulating Fetch in React Components:
javascript
// MyComponent.js
import React, { useEffect, useState } from 'react';

const MyComponent = () => {
const [data, setData] = useState(null);

useEffect(() => {
const fetchData = async () => {
const response = await fetch('https://api.example.com/data');
const result = await response.json();
setData(result);
};
fetchData();
}, []);

return (
<div>
{data ? <span>{data.message}</span> : <span>Loading...</span>}
</div>
);
};

export default MyComponent;
  1. Testing React Components with Async Data:
javascript
// __tests__/MyComponent.test.js
import React from 'react';
import { render, waitFor, screen } from '@testing-library/react';
import MyComponent from '../MyComponent';

beforeEach(() => {
global.fetch = jest.fn(() =>
Promise.resolve({
json: () => Promise.resolve({ message: 'datos mockeados' })
})
);
});

test('MyComponent displays data after loading', async () => {
render(<MyComponent />);

expect(screen.getByText('Loading...')).toBeInTheDocument();

await waitFor(() => expect(screen.getByText('datos mockeados')).toBeInTheDocument());
});

Placeholder for image: [A flowchart showing how Jest handles asynchronous operations with promises, async/await, and timers]


With these examples, you now have a solid understanding of how to handle asynchronous tests in Jest. In the next section, we will explore organizing and structuring tests in Jest to keep your test suite clean and manageable.


Support Chuck’s Academy!

Enjoying this course? I put a lot of effort into making programming education free and accessible. If you found this helpful, consider buying me a coffee to support future lessons. Every contribution helps keep this academy running! ☕🚀

Buy Me A Coffee

Chat with Chuck

Loading...
Chat with Chuck AI