The method of testing this reaction depends on the context to imitate the scenarios of real life

In this post, I will walk during my thinking process to test the context -based reaction components, using the test library. My goal is to explore a different approach to testing these components, studying the pros and cons of using Mucks for the test without mocking the context. We will look at how each approach affects the reliability of the tests, and I will share visions about when and why it may be one way more useful than the other in realistic applications.
What should you know?
- What reactjs is used for (maybe some applications have already been written)
- What is Fit
What is the context of the reaction
The context of Reactjs appeared as a solution for a common problem in the structure of the Reactjs ingredients: drilling the stent. The pillar of the stent occurs when we have a series of ingredients that need access to the same data set. The context mechanism allows components to share the same data set as long as the context itself is the first descendant.
In Reactjs documents, the context of retaining the topic is used, as the other component may need this information, documents are used to deal with that instead of passing the value through the supports. Another example is the use of the context to keep the application planning, in the example of Json-Tool App.tsX that surpasses the application using the Defautlayout context is available for all applications.
App for this example
For example, the feature will be used. It is an application that allows users to switch between light/dark features. The application is also used in official documents Reactjs. This application consists of a simple switch that turns between the place of light and the mode of the dark appearance. The application is simple as it happens and we can draw everything in one file:
import { createContext, useContext, useState } from 'react'
const ThemeContext = createContext('light')
function Page() {
const theme = useContext(ThemeContext)
return (
)
}
function App() {
const [theme, setTheme] = useState('light')
return (
)
}
export default App
In this app, we have two main components: App
and Page
. the App
The component works as a major component and contains the condition for the current topic, which can be “light” or “dark”. It also includes a button that wears the characteristic between light and dark conditions. the Page
The component is a child App
The context of the feature is consumed to display the current feature. Button App
The component is a simple switch button, when clicking on it, it replaces the feature and updates the value of the context accordingly.
Test ignition
Usually in any application, we must focus on the type of test that we want to do, and any segment we want to address. For example, we can target one component, instead of the entire application. In our example, we will start with the component of the page. Which will require us to use test tests to test it.
The test test comes from the same application structure, as it depends on the context, to change it, the value must be changed as well.
Test
To start our test approach with context in Reactjs, we will start writing the first test:
import { render, screen } from '@testing-library/react'
import { Page } from './Page'
describe('', () => {
it('should render light as default theme', () => {
render()
expect(screen.getByText('current theme: light')).toBeInTheDocument()
})
})
This test will be passed as expected, given that the subject of light is set to be the default excellence in themeconxt. We can even test the leadership of this first example, however, things become interesting in the second test, when we are interested in the dark topic. To reach a dark feature, we need to start using TestGiven that we rely on the context of Reactjs to do so. The second test brings vi.mock
To the mix as well vi.mocked
. Note that the second test to be written also requires changing the first test.
import { render, screen } from '@testing-library/react'
import { Page } from './Page'
import { useContext } from 'react'
vi.mock('react', () => {
return {
...vi.importActual('react'),
useContext: vi.fn(),
createContext: vi.fn()
}
})
describe('', () => {
it('should render light as default theme', () => {
vi.mocked(useContext).mockReturnValue('light')
render()
expect(screen.getByText('current theme: light')).toBeInTheDocument()
})
it('should render dark theme', () => {
vi.mocked(useContext).mockReturnValue('dark')
render()
expect(screen.getByText('current theme: dark')).toBeInTheDocument()
})
})
Both test cases are now used for fake to test the app. If we change the return data from the context, the test will also change. The point of attention here is:
- We are mocking the context of Reactjs, which raises “Do not make fun of what you do not have a principle”
- The test has become more lengthy, as we are required to use the irony to do so
- The two tests that we have written do not reflect the user interaction with the application. We know that the characteristic will change when pressing the switch button.
Without tests
The next approach is to use the context included in our application, without isolating it or using any test. If we follow this approach with TDD, we can start with a very simple test that mimics how the user will act:
import { render, screen } from '@testing-library/react'
import App from './App'
import userEvent from '@testing-library/user-event'
describe('', () => {
it('should render toggle button', () => {
render()
expect(screen.getByText('Toggle')).toBeInTheDocument()
})
})
Then follow the second test, we would like to set the subject of light by default:
import { render, screen } from '@testing-library/react'
import App from './App'
import userEvent from '@testing-library/user-event'
describe('', () => {
it('should render toggle button', () => {
render()
expect(screen.getByText('Toggle')).toBeInTheDocument()
})
it('should render light as default theme', () => {
render()
expect(screen.getByText('current theme: light')).toBeInTheDocument()
})
})
Last but not least, replace the feature:
import { render, screen } from '@testing-library/react'
import App from './App'
import userEvent from '@testing-library/user-event'
describe('', () => {
it('should render toggle button', () => {
render()
expect(screen.getByText('Toggle')).toBeInTheDocument()
})
it('should render light as default theme', () => {
render()
expect(screen.getByText('current theme: light')).toBeInTheDocument()
})
it('should render dark theme on toggle', async () => {
const user = userEvent.setup()
render()
await user.click(screen.getByText('Toggle'))
expect(screen.getByText('current theme: dark')).toBeInTheDocument()
})
})
Points of interest in this strategy:
- It is not necessary to test, as it makes the test with a code less
- The test behavior matches what the user will do in the real application
The pros and cons of each approach
In these sections, we will go to the pros and cons of each approach regarding different characteristics.
Re -create the pillars
Use the test test for context makes the test fragile for this type of change. The re -representation of the use of USContext with the supports makes the test automatically for failure even when the behavior is not. The use of the option that does not use the test supports the re -expulsion in this sense. In the book “Re -Create Great Software Projects”, authors Stephen Rock and Martin Libert filmed a scenario similar to what I mention here. One of the problems they discussed is related to re -creation and change of class structures, it is quoted by the C3 project:
About every 3 or 4 iterations we do a refactoring that causes us to toss or otherwise radically
modify a group of classes. The tests will either go away or be changed to reflect the classes’ new
behavior. We are constantly splitting classes up and moving behavior around. This may or may not affect the UnitTests
Ideally to overcome this situation, unit tests will be written based on “API stable” and it will also not be necessary to change the API system at times. Therefore, the solution proposed by the authors is to clarify mechanical admission tests.
Create a dedicated context
The same occurs to use a dedicated context instead of relying on the context provider directly from the Reactjs. Using the option without testing the test allows the intention.
conclusion
In this guide, we explored how to test the ingredients that depend on context, without the need for tests, which makes the tests more clear, closer to the real user reactions and the mavules and negatives of each approach. Whenever possible, the use of the Simples approach that reflects the user reaction should be followed. However, when tests are needed, they should be used to target the test code maintenance. A simple test enables re -creation of the production code with confidence.
resources
The following steps
- Try to test more sophisticated scenarios that include multiple contexts or interfering service providers.
- Although we avoid mockery in this guide, there are necessary cases. Explore the advanced mockery techniques of those scenarios.