Original address: medium.com/codeclan/te… Translation address: github.com/xiao-T/note… The copyright of this article belongs to the original author. Translation is for study only.
This article will explain how to set it up and use itJest 和 EnzymeThe test passCreate React App (CRA)To create theReactApplications. We have some advice for those who are starting from scratch. However, there won’t be much to learn about React.
Jest and Enzyme are two different, but mutually reinforcing, tools that combine to provide more flexible and creative testing capabilities. We’ll talk a little bit about the differences.
Jest
Jest is a Javascript unit testing framework that Facebook uses to test the service and React applications.
CRA already has Jest built in; Separate installation is no longer required.
Jest is a test runner, assertion library, and emulation library.
Jest also provides snapshot testing, which allows you to create a snapshot of a component and compare it to the last saved snapshot. If the two do not match, the test fails. The snapshot will be saved in a folder named __snapshots__, which is in the same directory as the file under test. The snapshot should look something like this:
exports[`List shallow renders correctly with no props 1`] = `
Item 1
Item 1
`;
Copy the code
Snapshot testing must be combined with browser testing, and the snapshot must be validated at the outset to ensure that it outputs as expected.
Enzyme
Enzyme is a test library for React that makes it easier to assert, manipulate, and iterate through React components.
Enzyme, created by Airbnb, and added better functional methods, such as rendering components, finding elements, and interacting with elements.
It must be installed separately in CRA.
Jest and Enzyme
- Jest and Enzyme can both test React applications. Jest can also test other Javascript applications, but Enzyme can only test React.
- Jest can render components and snapshot tests separately, Enzyme just adds simpler methods.
- Enzyme can be used without Jest, but must be combined with another test runner.
To sum up:
- Jest is used as a test runner, assertion library, and emulator
- Enzyme provides additional test functions and interactions.
Set up the
Installation and configuration
If you are not using CRA, you need to install Jest:
npm install --save-dev jest babel-jest
Copy the code
Install the Enzyme:
npm install --save-dev enzyme enzyme-adapter-react-16 enzyme-to-json
Copy the code
Update package. Json:
"jest": {
"snapshotSerializers": ["enzyme-to-json/serializer"]}Copy the code
Enzyme -to- JSON provides better component formatting than Enzyme for easier snapshot comparison. When using snapshots, snapshotSerializers can even more clop repetitive code. If no serialization tool is specified, the component needs to be passed to the.tojson () method of the enzyme-to-json method every time a snapshot is compared for a match in the test, otherwise it is not required.
expect(toJson(rawRenderedComponent)).toMatchSnapshot();
Copy the code
By adding this configuration to package.json, you don’t need to call the JSON formatting method again when you call Jest’s.tomatchSnapshot ().
Create the setuptets.js file in./ SRC/setuptests.js:
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16'; configure({adapter: new Adapter() });
Copy the code
CRA will automatically search for this file. If you’re not using CRA, you’ll need to add this configuration in the same place in the snapshotSerializers:
"setupFiles": ["./src/setupTests.js"],
Copy the code
Create test files
Jest will look for all test files in a place that meets the following rules:
- folder
__tests__
In order to.js
Closing document - In order to
.test.js
Closing document - In order to
.spec.js
Closing document
It is convenient to put each test file in the same directory as the code to be tested. This makes more sense semantically and makes relative paths simpler (./MyComponent vs… /.. / MyComponent).
Here’s a demonstration of myComponent.test.js:
import React from 'react';
import { shallow } from 'enzyme';
import MyComponent from './MyComponent';
describe('MyComponent', () => {
it('should render correctly in "debug" mode', () = > {const component = shallow(<MyComponent debug />);
expect(component).toMatchSnapshot();
});
});
Copy the code
In a CRA environment, when NPM test is executed, all test files are run and the results are output to the terminal. Using the custom tag — –testPathPattern filename/, you can specify to run only specific files or use — –testPathIgnorePatterns filename/ to ignore specified files.
Mount, Shallow, Render
Import {mount, shallow, render} from 'enzyme';Copy the code
In order to test the component, the above method will definitely be used, as shown in the previous code.
Mounting
- Complete DOM rendering, including subcomponents
- This is ideal for situations where you need to interact with the DOM and fully test the component lifecycle
- Because the component is actually rendered into the DOM, it needs to be called every time the test is done so as not to affect other tests
.unmount()
- Allows direct access to props passed to the root component (including the default) and to child components.
Shallow
- Render only individual components, not child components. This is useful for pure unit testing where components need to be isolated. It prevents component test results from being affected by changes and bugs in subcomponents.
- In the Enzyme 3
shallow
Rendering also has access to the component’s lifecycle methods by default. - The props passed to the root component cannot be accessed (because they are not the default props), but they can be passed to child components and tested to see if the props passed have any on the componentimpact. And he said
shallow
You can test a component’s rendering, but not its element.
Render
- Render components into static HTML, including child components
- Cannot access the React lifecycle method
- Compared with the
mount
It costs less, but it also has fewer features
Testing
Basic component rendering
A simple non-interactive component:
it('should render correctly with no props', () = > {const component = shallow(<MyComponent/>);
expect(component).toMatchSnapshot();
});
it('should render banner text correctly with given strings', () = > {const strings = ['one'.'two'];
const component = shallow(<MyComponent list={strings} />);
expect(component).toMatchSnapshot();
});
Copy the code
The event
The Enzyme API has several ways to simulate events or user interactions. The mount method is used if you want to test the interaction of child components.
it('should be possible to activate button with Spacebar', () = > {const component = mount(<MyComponent />);
component
.find('button#my-button-one')
.simulate('keydown', { keyCode: 32 });
expect(component).toMatchSnapshot();
component.unmount();
});
Copy the code
The simulation method
Perhaps you simply want to verify that the method passed through prop works.
const clickFn = jest.fn();
describe('MyComponent', () => {
it('button click should hide component', () = > {const component = shallow(<MyComponent onClick={clickFn} />);
component
.find('button#my-button-two')
.simulate('click');
expect(clickFn).toHaveBeenCalled();
});
});
Copy the code
As things get more complicated, you might want to emulate one of the import methods in myComponent.js that returns a value, checks if it was called, and compares snapshots.
Imagine that we introduced a SaveToStorage object in myComponent.js that contains TryGetValue and TrySetValue methods. TryGetValue has a default return value of false. If it returns true, the component will change. They are used by two different buttons in the component.
Mock can also simulate this behavior, and jest. Fn can override methods within the component.
const mockTryGetValue = jest.fn((a)= > false);
const mockTrySetValue = jest.fn();
jest.mock('save-to-storage', () = > ({SaveToStorage: jest.fn().mockImplementation((a)= > ({
tryGetValue: mockTryGetValue,
trySetValue: mockTrySetValue,
})),
}));
describe('MyComponent', () => {
it('should set storage on save button click', () => {
mockTryGetValue.mockReturnValueOnce(true);
const component = mount(<MyComponent />);
component.find('button#my-button-three').simulate('click');
expect(mockTryGetValue).toHaveBeenCalled();
expect(component).toMatchSnapshot();
component.unmount();
});
});
Copy the code
conclusion
Jest has other assertion methods (including toEqual), and Enzyme has more methods for traversal and interaction (including first and setProps). Each document is well documented and offers more possibilities.
Using Jest and Enzyme together makes testing the React component easier and more readable.
Thanks for enjoying it! 🙂
If you liked this article, you can also check out these:
- Test React II with Jest and Enzyme
- Mock the ES and CommoJS modules with jest. Mock ()
- Use jest, jest-Axe, and react-testing-library to test the React application
- Simulate HTTP requests with Nock
resources
In addition to official documents and my own experience, I have found the following two articles very useful, and the article I wrote was inspired by them and solidified my knowledge:
- Test React component from Artem Sapegin
- Unit test of the React component from Vijay Thirugnanam
In addition to unit and integration testing, you’ll want to see visual regression testing, and I recommend following Differencify.