У меня проблемы с тестированием очень специфического варианта использования моих компонентов React. В этом случае у меня есть компонент, который отправляет действие при монтировании, а затем отправляет другое действие после получения результатов первой отправки.
Я полагаю, что проблема заключается в том, что энзимный shallow
метод не вызывает componentDidUpdate
в моем компоненте. Я воспроизвел проблему с помощью самого простого кода, который только мог, и подтвердил, что проблема исчезнет, если я использую mount
вместо shallow
. Однако документация фермента говорит, что начиная с версии 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"
Спасибо!