这是我的组件:
class App extends Component {
constructor(props) {
super(props);
this.state = {
value: 'foo'
};
}
onChange = (e) => {
this.setState({
value: e.currentTarget.value
});
};
render() {
return (
<div className="App">
<input
id="foo"
value={this.state.value}
onChange={this.onChange}
/>
</div>
);
}
}
这是我的测试:
import {shallow, mount} from 'enzyme';
it('fires onChange', () => {
let wrapper = mount(<App />);
wrapper.find('#foo').simulate('change', {currentTarget: {value: 'bar'}});
expect(wrapper.state().value).toBe('bar');
expect(wrapper.find('#foo').props().value).toBe('bar');
});
测试目前失败:
Expected value to be (using ===):
"bar"
Received:
"foo"
但是如果我mount
更改为shallow
,它就会通过。我不完全确定为什么,我想知道浅层渲染和装载渲染之间是否存在任何其他实际差异。
要修复测试,您可以尝试:
import { mount } from 'enzyme';
it('fires onChange', () => {
const wrapper = mount(<App />).find('#foo');
expect(wrapper.props().value).toBe('foo');
wrapper.props().onChange({ currentTarget: { value: 'bar' } });
expect(wrapper.props().value).toBe('bar');
});
用于澄清浅层、装载式和酶渲染之间的区别
浅
真实单元测试(隔离,无子级渲染(
简单浅层
调用:
- 构造 函数
- 呈现
浅层+布景道具
调用:
- componentWillReceiveProps
- 应该组件更新
- 组件将更新
- 呈现
浅 + 卸载
调用:
- 组件将卸载
安装
测试组件DidMount和componentDidUpdate的唯一方法。完整呈现,包括子组件。需要一个 DOM(jsdom,domino(。在执行时间上更加稳定。如果在 JSDOM 之前包含 react ,则可能需要一些技巧:
'require('fbjs/lib/ExecutionEnvironment'(.canUseDOM = true;
安装简单
调用:
- 构造 函数
- 呈现
- 组件迪德挂载
坐骑 + 设置道具
调用:
- componentWillReceiveProps
- 应该组件更新
- 组件将更新
- 呈现
- 组件DidUpdate
挂载 + 卸载
调用:
- 组件将卸载
呈现
仅调用呈现,但呈现所有子项。
所以我的经验法则是:
- 始终从浅层开始
- 如果应该测试 componentDidMount 或 componentDidUpdate,请使用 安装
- 如果要测试组件生命周期和子行为,请使用 安装
- 如果要测试开销低于装载的子级渲染 并且您对生命周期方法不感兴趣,请使用 render
渲染似乎有一个非常小的用例。我喜欢它,因为它似乎比要求 jsdom 更快捷,但正如@ljharb所说,我们无法真正用这个测试 React 内部。
我想知道是否可以像浅层一样使用渲染方法模拟生命周期方法?如果您能给我内部渲染的用例或您在野外看到的用例,我将不胜感激。
我也很想知道为什么 shallow 不调用 componentDidUpdate。
点赞去 https://gist.github.com/fokusferit/e4558d384e4e9cab95d04e5f35d4f913,https://github.com/airbnb/enzyme/issues/465#issuecomment-227697726 这基本上是问题评论的副本