如果你是 React 新手,我们建议使用 。 It is ready to use and ships with Jest! 您只需要添加 来渲染快照。
运行
如果你已经有一个应用,你仅需要安装一些包来使他们运行起来。 我们使用babel-jest
包和babel-preset-react
,从而在测试环境中转换我们代码。 可参考
运行
yarn add --dev jest babel-jest babel-preset-env babel-preset-react react-test-renderer
你的package.json
文件应该像下面这样(<current-version>
是当前包的最新版本号) 请添加脚本项目和 jest 配置:
// package.json
"dependencies": {
"react": "<current-version>",
"react-dom": "<current-version>"
},
"devDependencies": {
"babel-jest": "<current-version>",
"babel-preset-env": "<current-version>",
"babel-preset-react": "<current-version>",
"jest": "<current-version>",
"react-test-renderer": "<current-version>"
},
"scripts": {
"test": "jest"
}
// .babelrc
{
"presets": ["env", "react"]
}
准备工作已经完成!
让我们来为一个渲染超链接的 Link 组件创建快照测试
现在,使用React的test renderer和Jest的快照特性来和组件交互,获得渲染结果和生成快照文件:
// Link.react.test.js
import React from 'react';
import Link from '../Link.react';
import renderer from 'react-test-renderer';
test('Link changes the class when hovered', () => {
const component = renderer.create(
<Link page="http://www.facebook.com">Facebook</Link>,
);
let tree = component.toJSON();
expect(tree).toMatchSnapshot();
// manually trigger the callback
tree.props.onMouseEnter();
// re-rendering
tree = component.toJSON();
expect(tree).toMatchSnapshot();
// manually trigger the callback
tree.props.onMouseLeave();
// re-rendering
tree = component.toJSON();
expect(tree).toMatchSnapshot();
exports[`Link changes the class when hovered 1`] = `
<a
className="normal"
href="http://www.facebook.com"
onMouseEnter={[Function]}
onMouseLeave={[Function]}>
</a>
`;
exports[`Link changes the class when hovered 2`] = `
<a
className="hovered"
href="http://www.facebook.com"
onMouseEnter={[Function]}
onMouseLeave={[Function]}>
</a>
`;
exports[`Link changes the class when hovered 3`] = `
<a
className="normal"
href="http://www.facebook.com"
onMouseEnter={[Function]}
onMouseLeave={[Function]}>
</a>
`;
下次你运行测试时,渲染的结果将会和之前创建的快照进行比较。 代码变动时快照必须按顺序提交。 当快照测试失败,你需要去检查是否是你想要或不想要的变动。 如果变动符合预期,你可以通过jest -u
调用Jest从而重写存在的快照。
该示例代码在
快照测试与 Mocks, Enzyme 和 React 16
There's a caveat around snapshot testing when using Enzyme and React 16+. If you mock out a module using the following style:
jest.mock('../SomeDirectory/SomeComponent', () => 'SomeComponent');
Then you will see warnings in the console:
React 16 triggers these warnings due to how it checks element types, and the mocked module fails these checks. Your options are:
Render as text. This way you won't see the props passed to the mock component in the snapshot, but it's straightforward:jsjest.mock('./SomeComponent', () => () => 'SomeComponent');
Render as a custom element. DOM "custom elements" aren't checked for anything and shouldn't fire warnings. They are lowercase and have a dash in the name.jsjest.mock('./Widget', () => 'mock-widget');
Use
react-test-renderer
. The test renderer doesn't care about element types and will happily accept e.g.SomeComponent
. You could check snapshots using the test renderer, and check component behavior separately using Enzyme.
如果你想要断言和操纵您渲染的组件你可以使用 或 React 的 TestUtils。本例中我们使用 Enzyme。 本例中我们使用 Enzyme。
You have to run yarn add —dev enzyme
to use Enzyme. If you are using a React version below 15.5.0, you will also need to install react-addons-test-utils
.
Let's implement a checkbox which swaps between two labels:
// CheckboxWithLabel.js
import React from 'react';
export default class CheckboxWithLabel extends React.Component {
constructor(props) {
super(props);
this.state = {isChecked: false};
// bind manually because React class components don't auto-bind
// http://facebook.github.io/react/blog/2015/01/27/react-v0.13.0-beta-1.html#autobinding
this.onChange = this.onChange.bind(this);
}
}
render() {
return (
<label>
<input
type="checkbox"
checked={this.state.isChecked}
onChange={this.onChange}
/>
{this.state.isChecked ? this.props.labelOn : this.props.labelOff}
</label>
);
}
}
在这个例子中我们使用了 Enzyme 的。
// __tests__/CheckboxWithLabel-test.js
import React from 'react';
import {shallow} from 'enzyme';
import CheckboxWithLabel from '../CheckboxWithLabel';
test('CheckboxWithLabel changes the text after click', () => {
// Render a checkbox with label in the document
const checkbox = shallow(<CheckboxWithLabel labelOn="On" labelOff="Off" />);
expect(checkbox.text()).toEqual('Off');
checkbox.find('input').simulate('change');
expect(checkbox.text()).toEqual('On');
});
The code for this example is available at examples/enzyme.
If you need more advanced functionality, you can also build your own transformer. Instead of using babel-jest, here is an example of using babel:
// custom-transformer.js
'use strict';
const babel = require('babel-core');
const jestPreset = require('babel-preset-jest');
module.exports = {
process(src, filename) {
if (babel.util.canCompile(filename)) {
return babel.transform(src, {
filename,
presets: [jestPreset],
});
}
return src;
},
};
不要忘记安装 babel-core
和 babel-preset-jest
包使这个例子可以工作。
为了使这个与 Jest 一起工作,您需要更新您的 Jest 配置:。