Most AI projects fail. Yours doesn’t have to.
Reserve your spot today and get a production-ready Agent Blueprint in just 3 weeks
6
spots‍
‍available
Register for Your Agent Blueprint
About
Capabilities
Custom AgentsReliable RAGCustom Software DevelopmentEval Driven DevelopmentObservability
LangChainCase StudiesFocused Lab
Contact us
Back
Blog

Unsticking Your React Tests

Tips for testing complex React components using state, context, and controlled inputs.

May 23, 2025

By
Share:

Testing React components can be tricky, especially when dealing with complex scenarios involving state management, context providers, or controlled components. While React Testing Library is an excellent tool for testing components in a way that mirrors how users interact with them, some situations require additional set up or specific patterns to test effectively.

In this post, I'll walk through several challenging testing scenarios I've encountered and share the strategies I use to handle them. We'll look at testing controlled components with state management, working with React Context and reducers, and share some helpful utilities for dealing with common testing roadblocks.

The examples here assume familiarity with React Testing Library and a test framework like Jest or Vitest. If you're new to writing tests for React components, I'd recommend starting with the React Testing Library documentation before diving into these more advanced patterns.

Test Harness

As your React application grows, you may split up larger components by extracting out smaller components to encapsulate specific logic, or to reuse common components in multiple places. The example I have here is an EmailField component - a text field that shows an error message if the value is invalid.

This EmailField component has specific validation rules and expected behaviors - let's try to write a unit test.

Typically, this EmailField component would be a child of a larger component, such as a sign up form, or login page. In that case, you don’t necessarily need to use this “Test Harness” approach. Instead, you can verify the EmailField behavior by writing larger “integration-style” tests of the larger component that more closely resembles how a “real user” will interact with your application.

If testing indirectly through the larger component isn’t an option - maybe the EmailField is part of your component library, or you don’t want to deal with any additional behavior or side effects happening in the larger component - this approach can help you test the EmailField in isolation.

React Context + Reducer

When a component uses data from a context provider, it will need some additional setup when testing that component in isolation. I’ll be borrowing the To-Do app example from the React documentation (https://react.dev/learn/scaling-up-with-reducer-and-context), and walking through a test writing example.

Here's an implementation outline for the context provider and app components.

Let's try to write some tests:

First, let's test that we see all the tasks.

Now let's write a test for adding a new task:

If you want more control over the initial state of the test, you can create a Wrapper component to manage the context provider setup. For example, you might want to customize the initial task list for each unit test.

Assorted Helpers

Here are a couple code snippets that I've brought from project to project to streamline React testing.

Run Pending Promises

This is helpful to “tick forward” in the test to process queued Promises and start the next React render cycle. For example, if your component fires an asynchronous API call on initial load, you can render then run pending promises to resolve the API call promise.

React Native AnimatedView Mock

My team encountered this issue when testing button presses in React Native code. Our application created custom buttons using the TouchableOpacity component, which had a built-in animation when the component was pressed. This caused a "Warning: An update to ForwardRef inside a test was not wrapped in act(...)" console error to appear in tests where the button was pressed.

To address the warning, we mocked the <Animated.View> component to return a normal view, but made sure to keep the same props from the original component. This was inspired by the discussion from this Github issue on react-native-testing-library - some previous answers suggested a similar mock that removed the animated "wrapper" entirely. However, we found that this caused tests to fail unexpectedly when verifying specific properties of the "wrapper", such as disabled state or accessibility labels.

Conclusion

As your React application grows and becomes more complex, it can be tricky to find the right level of isolation and mocking when writing component tests - I'd need another blog post or two for that discussion! But the most important thing is to write tests that are useful: they should verify behaviors you care about, fail for the right reasons, and be easy to adapt to meet future needs. I hope these React testing strategies will help you accomplish that in your own projects.

Your message has been sent!

We’ll be in touch soon. In the mean time check out our case studies.

See all projects
/Contact Us

From concept to table: let’s build your loyalty app

Modernize your legacy with Focused

Get in touch
Focused

433 W Van Buren St Suite 1100-C
Chicago, IL 60607
‍work@focused.io
‍
(708) 303-8088

‍

About
Leadership
Capabilities
Case Studies
Focused Lab
Careers
Contact
© 2026 Focused. All rights reserved.
Privacy Policy
Most AI projects fail. Yours doesn’t have to.
Reserve your spot today and get a production-ready Agent Blueprint in just 3 weeks
6
spots‍
‍available
Register for Your Agent Blueprint