我无法测试我的React组件的一个非常特定的用例。在这种情况下,我有一个组件,该组件在安装时分派一个动作,然后在第一次分派的结果进入后分派另一个动作。
我认为问题出在酶的shallow
方法中而不在组件中调用componentDidUpdate
。我用最简单的代码重现了该问题,并确认如果我使用mount
而不是shallow
,该问题就消失了。但是,enzyme's documentation说,从版本3开始,shallow
确实调用了React的生命周期方法,例如componentDidUpdate
。当然,我不能在测试中使用mount
,因为我不想挂载整个树(对我而言,这意味着要装载整个应用程序)。
因此,我想知道:这是否是酶的错误,还是我在使用该库时缺少某些东西?
这是我的代码示例:
import * as React from 'react';
import { connect } from 'react-redux';
import { createStore } from 'redux';
import { shallow } from 'enzyme';
import sinon from 'sinon';
const actions = {
// This would fetch a resource on the network.
getList: () => {},
receiveList: list => {
return {
type: 'RECEIVE_LIST',
list,
};
},
// This would fetch a list of resources on the network.
getObjects: () => {},
};
const reducer = (state = { list: [] }, action) => {
switch (action.type) {
case 'RECEIVE_LIST':
return { ...state, list: action.list };
default:
return state;
}
};
class MyAppBase extends React.Component {
componentDidMount() {
this.props.dispatch(actions.getList());
}
componentDidUpdate(nextProps) {
if (nextProps.list !== this.props.list) {
this.props.dispatch(actions.getObjects(nextProps.list));
}
}
render() {
return null;
}
}
const MyApp = connect(state => { return { list: state.list }; })(MyAppBase);
describe('<MyApp>', () => {
it('fetches objects once list is received', () => {
// Mock actions that call the network.
sinon.stub(actions, 'getList');
actions.getList.returns({type: 'whatever'});
sinon.stub(actions, 'getObjects');
actions.getObjects.returns({type: 'whatever'});
// Create a redux store.
const store = createStore(reducer);
// Create the component.
const wrapper = shallow(<MyApp store={store} />);
// Verify that `componentDidMount` was called but not `componentDidUpdate`.
expect(actions.getList.callCount).toEqual(1);
expect(actions.getObjects.callCount).toEqual(0);
// Dispatch an action that will change the redux store.
store.dispatch(actions.receiveList([ 'aa', 'bb' ]));
// Expect the `componentDidUpdate` method to be called.
expect(actions.getObjects.callCount).toEqual(1);
// This doesn't work, for some reason `componentDidUpdate` is never called.
});
});
我为此使用的软件包版本:
"react": "16.6.0",
"react-dom": "16.6.0",
"react-redux": "5.1.0",
"redux": "4.0.1",
"enzyme": "3.7.0",
"enzyme-adapter-react-16": "1.6.0",
"sinon": "7.1.0"
谢谢!
答案 0 :(得分:1)
酶的“浅”方法似乎不完全支持“ componentDidUpdate”方法。
安装了<form th:object="${myobject}">
<select class="selectpicker"
id="tech"
th:field="*{technology}">
<option th:each="technology:${technology}"
th:value="${technology}" th:text="${technology}">
</option></select>
<form>
的组件似乎仅在调用shallow
之后才调用componentDidUpdate
。商店以新状态更新也没关系,包装器也没有更新。
可以通过更改测试以执行以下操作来确认:
wrapper.setProps()
一种解决方法是在// Dispatch an action that will change the redux store.
store.dispatch(actions.receiveList([ 'aa', 'bb' ]));
// Will print '[]'
console.log(wrapper.instance().props.list);
// Create a new wrapper with the current store:
const wrapper2 = shallow(<MyApp store={store} />);
// Will print '['aa', 'bb']'
console.log(wrapper2.instance().props.list)
之后调用setProps
(如果可行,最好使用store.dispatch
代替mount
):
shallow
此外,// Dispatch an action that will change the redux store.
store.dispatch(actions.receiveList([ 'aa', 'bb' ]));
// Manually cause componentDidUpdate to trigger
wrapper.setProps({
list: ['aa', 'bb']
});
可以通过componentDidUpdate
方法来触发,以单击或更改按钮或输入。