react-hooks-testing-library
🐏 Simple and complete React hooks testing utilities that encourage good testing practices.
Top Related Projects
🐐 Simple and complete React DOM testing utilities that encourage good testing practices.
JavaScript Testing utilities for React
Fast, easy and reliable testing for anything that runs in a browser.
Quick Overview
React Hooks Testing Library is a lightweight utility that simplifies the process of testing React hooks. It provides a simple and intuitive API for rendering hooks in a test environment, allowing developers to test custom hooks in isolation without the need for a full component render.
Pros
- Easy to use and integrates well with popular testing frameworks like Jest
- Allows testing of complex hooks with dependencies and side effects
- Provides a way to test hooks in isolation, improving test clarity and maintainability
- Supports both synchronous and asynchronous testing scenarios
Cons
- Limited to testing hooks only, not suitable for full component testing
- May require additional setup for more complex scenarios involving context or other React features
- Learning curve for developers new to testing React hooks
- Some edge cases might be challenging to test without additional mocking or setup
Code Examples
- Testing a simple custom hook:
import { renderHook, act } from '@testing-library/react-hooks';
import useCounter from './useCounter';
test('should increment counter', () => {
const { result } = renderHook(() => useCounter());
act(() => {
result.current.increment();
});
expect(result.current.count).toBe(1);
});
- Testing an asynchronous hook:
import { renderHook, act } from '@testing-library/react-hooks';
import useAsync from './useAsync';
test('should handle async operations', async () => {
const { result, waitForNextUpdate } = renderHook(() => useAsync());
expect(result.current.loading).toBe(false);
act(() => {
result.current.run();
});
expect(result.current.loading).toBe(true);
await waitForNextUpdate();
expect(result.current.loading).toBe(false);
expect(result.current.data).toBeDefined();
});
- Testing a hook with context:
import { renderHook } from '@testing-library/react-hooks';
import { ThemeProvider } from './ThemeContext';
import useTheme from './useTheme';
test('should use theme from context', () => {
const wrapper = ({ children }) => (
<ThemeProvider initialTheme="dark">{children}</ThemeProvider>
);
const { result } = renderHook(() => useTheme(), { wrapper });
expect(result.current.theme).toBe('dark');
});
Getting Started
To start using React Hooks Testing Library, follow these steps:
-
Install the library:
npm install --save-dev @testing-library/react-hooks
-
Import the necessary functions in your test file:
import { renderHook, act } from '@testing-library/react-hooks';
-
Write your tests using the
renderHook
function to render your custom hooks andact
for updating hook state:test('my custom hook', () => { const { result } = renderHook(() => useMyCustomHook()); // Assert initial state expect(result.current.value).toBe(initialValue); // Act on the hook act(() => { result.current.updateValue(newValue); }); // Assert updated state expect(result.current.value).toBe(newValue); });
Competitor Comparisons
🐐 Simple and complete React DOM testing utilities that encourage good testing practices.
Pros of react-testing-library
- Focuses on testing components from a user's perspective, encouraging better test practices
- Provides a more comprehensive set of utilities for testing entire React components
- Supports testing of DOM events and asynchronous operations out of the box
Cons of react-testing-library
- May be overkill for testing simple custom hooks
- Requires more setup and boilerplate code for testing hooks in isolation
- Can be slower for hook-specific tests due to rendering full components
Code Comparison
react-testing-library:
import { render, fireEvent } from '@testing-library/react';
test('increments counter', () => {
const { getByText } = render(<Counter />);
fireEvent.click(getByText(/increment/i));
expect(getByText(/count: 1/i)).toBeInTheDocument();
});
react-hooks-testing-library:
import { renderHook, act } from '@testing-library/react-hooks';
test('increments counter', () => {
const { result } = renderHook(() => useCounter());
act(() => {
result.current.increment();
});
expect(result.current.count).toBe(1);
});
The react-testing-library is better suited for testing full components and user interactions, while react-hooks-testing-library provides a more focused approach for testing custom hooks in isolation. Choose based on your specific testing needs and the complexity of your components or hooks.
JavaScript Testing utilities for React
Pros of Enzyme
- More comprehensive API for component manipulation and traversal
- Supports shallow rendering for isolated unit testing
- Longer history and larger community support
Cons of Enzyme
- Requires more setup and configuration
- Can encourage testing implementation details rather than behavior
- Less focus on accessibility and user-centric testing
Code Comparison
Enzyme:
const wrapper = shallow(<MyComponent />);
expect(wrapper.find('.my-class').text()).toBe('Expected Text');
wrapper.find('button').simulate('click');
React Hooks Testing Library:
const { result } = renderHook(() => useMyHook());
expect(result.current.value).toBe('Expected Value');
act(() => {
result.current.setValue('New Value');
});
Key Differences
- Enzyme focuses on component testing, while React Hooks Testing Library specializes in testing hooks
- Enzyme provides more methods for interacting with component internals
- React Hooks Testing Library promotes a more user-centric testing approach
- Enzyme supports both class and functional components, while React Hooks Testing Library is designed specifically for hooks in functional components
Use Cases
- Choose Enzyme for comprehensive component testing, especially with class components
- Opt for React Hooks Testing Library when focusing on testing custom hooks or functional components with hooks
Fast, easy and reliable testing for anything that runs in a browser.
Pros of Cypress
- Comprehensive end-to-end testing framework for web applications
- Real-time browser testing with automatic waiting and retrying
- Rich ecosystem with plugins and integrations
Cons of Cypress
- Steeper learning curve due to its extensive feature set
- Limited to testing web applications (no native mobile support)
- Can be slower for large test suites compared to unit testing
Code Comparison
React Hooks Testing Library:
import { renderHook, act } from '@testing-library/react-hooks';
import useCounter from './useCounter';
test('should increment counter', () => {
const { result } = renderHook(() => useCounter());
act(() => { result.current.increment(); });
expect(result.current.count).toBe(1);
});
Cypress:
describe('Counter', () => {
it('should increment counter', () => {
cy.visit('/counter');
cy.get('[data-testid="count"]').should('have.text', '0');
cy.get('[data-testid="increment"]').click();
cy.get('[data-testid="count"]').should('have.text', '1');
});
});
Summary
React Hooks Testing Library is focused on testing React hooks in isolation, making it ideal for unit testing custom hooks. Cypress, on the other hand, is a comprehensive end-to-end testing framework that simulates user interactions in a real browser environment. While React Hooks Testing Library is lightweight and fast for hook-specific tests, Cypress offers a more robust solution for testing entire web applications, albeit with a steeper learning curve and longer execution times for large test suites.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
react-hooks-testing-library
Simple and complete React hooks testing utilities that encourage good testing practices.
Read The Docs
A Note about React 18 Support
If you are using the current version of react-testing-library
, replace
import { renderHook } from '@testing-library/react-hooks'
with
import { renderHook } from '@testing-library/react'
Once replaced, @testing-library/react-hooks
can be uninstalled.
Details
As part of the changes for React 18, it has been decided that the renderHook
API provided by this
library will instead be included as official additions to both react-testing-library
(PR) and
react-native-testing-library
(PR) with the intention being
to provide a more cohesive and consistent implementation for our users.
Please be patient as we finalise these changes in the respective testing libraries.
In the mean time you can install @testing-library/react@^13.1
Table of Contents
- The problem
- The solution
- When to use this library
- When not to use this library
- Example
- Installation
- API
- Contributors
- Issues
- LICENSE
The problem
You're writing an awesome custom hook and you want to test it, but as soon as you call it you see the following error:
Invariant Violation: Hooks can only be called inside the body of a function component.
You don't really want to write a component solely for testing this hook and have to work out how you were going to trigger all the various ways the hook can be updated, especially given the complexities of how you've wired the whole thing together.
The solution
The react-hooks-testing-library
allows you to create a simple test harness for React hooks that
handles running them within the body of a function component, as well as providing various useful
utility functions for updating the inputs and retrieving the outputs of your amazing custom hook.
This library aims to provide a testing experience as close as possible to natively using your hook
from within a real component.
Using this library, you do not have to concern yourself with how to construct, render or interact with the react component in order to test your hook. You can just use the hook directly and assert the results.
When to use this library
- You're writing a library with one or more custom hooks that are not directly tied to a component
- You have a complex hook that is difficult to test through component interactions
When not to use this library
- Your hook is defined alongside a component and is only used there
- Your hook is easy to test by just testing the components using it
Example
useCounter.js
import { useState, useCallback } from 'react'
function useCounter() {
const [count, setCount] = useState(0)
const increment = useCallback(() => setCount((x) => x + 1), [])
return { count, increment }
}
export default useCounter
useCounter.test.js
import { renderHook, act } from '@testing-library/react-hooks'
import useCounter from './useCounter'
test('should increment counter', () => {
const { result } = renderHook(() => useCounter())
act(() => {
result.current.increment()
})
expect(result.current.count).toBe(1)
})
More advanced usage can be found in the documentation.
Installation
npm install --save-dev @testing-library/react-hooks
Peer Dependencies
react-hooks-testing-library
does not come bundled with a version of
react
to allow you to install the specific version you want
to test against. It also does not come installed with a specific renderer, we currently support
react-test-renderer
and
react-dom
. You only need to install one of them,
however, if you do have both installed, we will use react-test-renderer
as the default. For more
information see the
installation docs. Generally, the
installed versions for react
and the selected renderer should have matching versions:
npm install react@^16.9.0
npm install --save-dev react-test-renderer@^16.9.0
NOTE: The minimum supported version of
react
,react-test-renderer
andreact-dom
is^16.9.0
.
API
See the API reference.
Contributors
Thanks goes to these wonderful people (emoji key):
This project follows the all-contributors specification. Contributions of any kind welcome!
Issues
Looking to contribute? Look for the Good First Issue label.
ð Bugs
Please file an issue for bugs, missing documentation, or unexpected behavior.
ð¡ Feature Requests
Please file an issue to suggest new features. Vote on feature requests by adding a ð. This helps maintainers prioritize what to work on.
â Questions
For questions related to using the library, you can raise issue here, or visit a support community:
LICENSE
MIT
Top Related Projects
🐐 Simple and complete React DOM testing utilities that encourage good testing practices.
JavaScript Testing utilities for React
Fast, easy and reliable testing for anything that runs in a browser.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot