HomeAbout Me

React Testing 7: testing with context and a custom render method

By Daniel Nguyen
Published in React JS
September 08, 2025
1 min read
React Testing 7: testing with context and a custom render method

testing with context and a custom render method

Background

A common question when testing React components is what to do with React components that use context values. If you take a step back and consider the guiding testing philosophy of writing tests that resemble the way our software is used, then you’ll know that you want to render your component with the provider:

render(
<ContextProvider>
<ComponentToTest />
</ContextProvider>,
)

The one problem with this is if you want to re-render the <ComponentToTest /> (for example, to give it new props and test how it responds to updated props), then you have to include the context providers:

const {rerender} = render(
<ContextProvider>
<ComponentToTest />
</ContextProvider>,
)
rerender(
<ContextProvider>
<ComponentToTest newProp={true} />
</ContextProvider>,
)

This is kind of annoying, so instead, you can provide a wrapper option and that will ensure that rerenders are wrapped as well:

function Wrapper({children}) {
return <ContextProvider>{children}</ContextProvider>
}
const {rerender} = render(<ComponentToTest />, {wrapper: Wrapper})
rerender(<ComponentToTest newProp={true} />)

📜 https://testing-library.com/docs/react-testing-library/api#wrapper

This Wrapper could include providers for all your context providers in your app: Router, Theme, Authentication, etc.

To take it further, you could create your own custom render method that does this automatically:

import {render as rtlRender} from '@testing-library/react'
// "rtl" is short for "react testing library" not "right-to-left" 😅
function render(ui, options) {
return rtlRender(ui, {wrapper: Wrapper, ...options})
}
// then in your tests, you don't need to worry about context at all:
const {rerender} = render(<ComponentToTest />)
rerender(<ComponentToTest newProp={true} />)

From there, you can put that custom render function in your own module and use your custom render method instead of the built-in one from React Testing Library. Learn more about this from the docs:

📜 https://testing-library.com/docs/react-testing-library/setup

Exercise

In this exercise, we have an “Easy Button” that’s styled differently based on the Theme context. Your job is to assert on the styles it has, but you first need to render the UI with the ThemeProvider (and set the initialTheme value).

Extra Credit

1. 💯 add a test for the dark theme

Should mostly be a copy/paste and change the initialTheme and assertion a bit.

2. 💯 create a custom render method

The duplication is cramping my style. Create a custom render method that encapsulates this shared logic. It’ll need to accept an option for the theme (dark or light).

3. 💯 swap @testing-library/react with app test utils

We’ve actually already created a custom render method for this! So swap your import of @testing-library/react with test/test-utils which you can find in ./src/test/test-utils.js.

🦉 Elaboration and Feedback

After the instruction, if you want to remember what you’ve just learned, then fill out the elaboration and feedback form:

https://ws.kcd.im/?ws=Testing%20React%20Applications%20%F0%9F%A7%90&e=07%3A%20testing%20with%20context%20and%20a%20custom%20render%20method&em=

Solution

import * as React from 'react'
import {render as rtlRender} from '@testing-library/react'
import {ThemeProvider} from 'components/theme'
function render(ui, {theme = 'light', ...options} = {}) {
const Wrapper = ({children}) => (
<ThemeProvider initialTheme={theme}>{children}</ThemeProvider>
)
return rtlRender(ui, {wrapper: Wrapper, ...options})
}
export * from '@testing-library/react'
// override React Testing Library's render with our own
export {render}
import * as React from 'react'
import {render, screen} from 'test/test-utils'
import EasyButton from '../../components/easy-button'
test('renders with the light styles for the light theme', () => {
render(<EasyButton>Easy</EasyButton>, {theme: 'light'})
const button = screen.getByRole('button', {name: /easy/i})
expect(button).toHaveStyle(`
background-color: white;
color: black;
`)
})
test('renders with the dark styles for the dark theme', () => {
render(<EasyButton>Easy</EasyButton>, {theme: 'dark'})
const button = screen.getByRole('button', {name: /easy/i})
expect(button).toHaveStyle(`
background-color: black;
color: white;
`)
})

Tags

#React

Share

Previous Article
React Testing 6: mocking Browser APIs and modules

Table Of Contents

1
testing with context and a custom render method
2
Solution

Related Posts

React Testing 8: Testing custom hook
September 09, 2025
1 min
© 2025, All Rights Reserved.
Powered By

Quick Links

About Me

Legal Stuff

Social Media