如何在连接的 React-Redux 组件中测试 componentWillMount?

How to test componentWillMount inside a connected React-Redux component?

我有以下智能组件,它使用 componentWillMount 生命周期方法进行异步调用以获取数据。我正在为它编写测试,但我无法测试该函数是否被调用以及是否调用它是在组件安装之前调用的。它们是需要涵盖的重要案例。

智能组件代码如下:

const mapStateToProps = (state) => {   const context = state.context;  return {
    isError: context.error,   }; };

const options = {   componentWillMount: (props) => {
    const { dispatch } = props;
    dispatch(fetchContextUser());   }, };

export function App(props) {   return (
    <div className="app">
      { props.isError ? (<ContextError />) : (<Main />) }
      { props.children }
    </div>   ); }

App.propTypes = {   children: PropTypes.object, // eslint-disable-line react/forbid-prop-types   isError: PropTypes.bool.isRequired, // eslint-disable-line react/forbid-prop-types };

export default connect(mapStateToProps, null)(functional(App, options));

我正在使用 Enzyme、Chai 和其他模拟适配器来测试此组件。测试块如下:

describe.only('Render Connected Component', () => {   let store;   beforeEach(() => {
    store = mockStore({
      context: {
        error: false,
      },
    });   });   it('Should render connected components', () => {
    const connectedWrapper = mount(
      <Provider store={store}>
        <ConnectedApp />
      </Provider>
    );
    expect(connectedWrapper).to.be.present();   }); });

I just want to test two things :

1.) fetchContextUser is called 2.) fetchContextUser is called before the component gets mounted

我认为你只需要测试 componentWillMount 方法调用 fetchContextUser 动作,因为你必须相信 ReactJS 会调用componentWillMount 方法在它被安装之前,所以,那个前提测试你的第二个案例。 所以,为了测试第一个案例,我认为你可以这样做:

import sinon from 'sinon';
...

it('It calls fetchContextUser when calls componentWillMount', () => {
  const fetchContextUserSpy = sinon.spy();
  const wrapper = shallow(<App fetchContextUser={fetchContextUserSpy} />);
  fetchContextUserSpy.reset(); //reset the spy to avoid unwanted calls
  wrapper.instance().componentWillMount(); // Call componentWillMount directly
  expect(fetchContextUserSpy.calledOnce).to.be.true; // Expect that after call componentWillMount() the fetchContextUserSpy was called once

在此测试中,您只需直接调用 componentWillMount() 函数并期望调用 fetchContextUserSpy,以便测试您的 案例 1。 我正在使用 sinon.js 来测试函数何时被调用。

同样,您的 案例 2 不需要测试,因为 ReactJS 保证在安装组件之前调用 componentWillMount 方法。

============================================= ============================

用功能组件试试这个

it('It calls fetchContextUser when mounted', () => {
  const fetchContextUserSpy = sinon.spy();
  const wrapper = shallow(<App fetchContextUser={fetchContextUserSpy} />);
  expect(fetchContextUserSpy.calledOnce).to.be.true; // Expect that the component calls the fetchContextUserSpy
});

我认为@pedro-jiminez 很接近,但这里缺少两个元素:

  • 为了在酶中调用 componentWillMount,您需要使用 mount,而不是 shallow
  • 该答案假定 fetchContextUser 是道具,可以用间谍代替。在这种情况下,您可能希望在测试中存根 store.dispatch 并断言它是用 fetchContextUser 调用的,假设这只是一个纯函数。

所以测试看起来像:

describe.only('Render Connected Component', () => {
  let store;
  beforeEach(() => {
    store = mockStore({
      context: {
        error: false,
      },
    });
    // stub dispatch
    sinon.stub(store.dispatch);
  });
  it('Should render connected components', () => {
    const connectedWrapper = mount(
      <Provider store={store}>
        <ConnectedApp />
      </Provider>
    );
    expect(connectedWrapper).to.be.present();
    // Now test dispatch called
    expect(store.dispatch.calledOnce).to.be.true;
    expect(store.dispatch.args[0][0]).to.deepEqual(fetchContextUser());
  });
});