Getting Started with React Testing
Creating test cases for React applications can ensure the reliability and maintainability of your code. Here’s a tutorial that takes you from basic to advanced React testing, using the popular testing library React Testing Library (RTL) along with Jest as the test runner.
Getting Started with React Testing
1. Setting Up the Environment
First, make sure you have a React project set up. If not, you can create one using Create React App:
npx create-react-app my-app
cd my-app
Then, install the necessary testing libraries:
npm install --save-dev @testing-library/react @testing-library/jest-dom jest
2. Basic Testing with Jest and React Testing Library
Let’s start by writing a simple test for a React component.
App.js
import React from 'react';
const App = () => {
return (
<div>
<h1>Hello, World!</h1>
</div>
);
};export default App;
App.test.js
import React from 'react';
import { render, screen } from '@testing-library/react';
import App from './App';
test('renders Hello, World!', () => {
render(<App />);
const helloElement = screen.getByText(/Hello, World!/i);
expect(helloElement).toBeInTheDocument();
});
To run the test, use:
npm test
3. Testing User Interactions
Next, let’s test a component with user interactions.
Button.js
import React, { useState } from 'react';
const Button = () => {
const [count, setCount] = useState(0); return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
};export default Button;
Button.test.js
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import Button from './Button';
test('increments count on button click', () => {
render(<Button />);
const buttonElement = screen.getByText(/Click me/i);
fireEvent.click(buttonElement);
fireEvent.click(buttonElement);
const countElement = screen.getByText(/You clicked 2 times/i);
expect(countElement).toBeInTheDocument();
});
4. Mocking API Calls
Testing components that make API calls involves mocking the API calls. We can use jest.mock
for this purpose.
User.js
import React, { useEffect, useState } from 'react';
const User = () => {
const [user, setUser] = useState(null); useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/users/1')
.then(response => response.json())
.then(data => setUser(data));
}, []); return (
<div>
{user ? <p>{user.name}</p> : <p>Loading...</p>}
</div>
);
};export default User;
User.test.js
import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import User from './User';
global.fetch = jest.fn(() =>
Promise.resolve({
json: () => Promise.resolve({ name: 'John Doe' }),
})
);test('fetches and displays user data', async () => {
render(<User />);
expect(screen.getByText(/Loading.../i)).toBeInTheDocument();
const userElement = await waitFor(() => screen.getByText(/John Doe/i));
expect(userElement).toBeInTheDocument();
});
5. Advanced Testing Techniques
5.1 Snapshot Testing
Snapshot testing can be used to ensure that the UI does not change unexpectedly.
MyComponent.js
import React from 'react';
const MyComponent = () => {
return (
<div>
<h1>Snapshot Test</h1>
</div>
);
};export default MyComponent;
MyComponent.test.js
import React from 'react';
import renderer from 'react-test-renderer';
import MyComponent from './MyComponent';
test('renders correctly', () => {
const tree = renderer.create(<MyComponent />).toJSON();
expect(tree).toMatchSnapshot();
});
5.2 Testing Custom Hooks
Testing custom hooks can be done using React’s renderHook
utility.
useCounter.js
import { useState } from 'react';
const useCounter = () => {
const [count, setCount] = useState(0);
const increment = () => setCount(count + 1);
const decrement = () => setCount(count - 1);
return { count, increment, decrement };
};export default useCounter;
useCounter.test.js
import { renderHook, act } from '@testing-library/react-hooks';
import useCounter from './useCounter';
test('should increment and decrement counter', () => {
const { result } = renderHook(() => useCounter()); act(() => {
result.current.increment();
});
expect(result.current.count).toBe(1); act(() => {
result.current.decrement();
});
expect(result.current.count).toBe(0);
});
Conclusion
This tutorial covered the basics and some advanced techniques for testing React applications using Jest and React Testing Library. You learned how to set up a testing environment, write tests for components and user interactions, mock API calls, perform snapshot testing, and test custom hooks. With these tools and techniques, you can ensure that your React application remains reliable and maintainable as it grows.