首页 > 解决方案 > 在componentDidMount中获取数据后如何测试反应组件?

问题描述

我有一个有条件呈现的反应组件(如果获取数据则呈现,否则返回 null),我想用jest & enzyme. 我遇到的问题是我想测试类中的一种方法,但.instance()一直返回 null 所以它不允许我测试实例。

我的代码看起来像这样

export default class MyComponent extends React.Component<Props, State> {
    componentDidMount() {
        this.props.fetchData.then(() => 
            this.setState({ loaded: true });
        );
    }

    methodThatIWantToTest() {
        //do some stuff here
    }

    render() {
        if (this.loaded) {
            // render stuff here
        } else {
            return null;
        }
    }
}

在测试中我想测试

describe('myComponent', () => {
   it('should do some stuff', () => {
      const shallowWrapper = shallow(<MyComponent {...props}/>);
      const method = shallowWrapper.instance().methodThatIWantToTest();
      ....such and such

   });
});

但它看起来MyComponent只返回 null 所以shallowWrapper.instance()也返回 null 。我尝试shallowWrapper.update()了很多其他的东西,但它似乎根本不想渲染。我如何等待我的组件更新然后开始expect声明?

有没有人和我有类似的问题并且知道如何解决这个问题?

标签: reactjsjestjsenzyme

解决方案


它是render结果而不是实例nullshallowWrapper.instance()是组件类的实例,不能null用于有状态组件。正如参考文献所述:

返回 (React 16.x)

ReactComponent:有状态的 React 组件实例。

null:如果无状态 React 组件被包装。

虽然shallowWrapper.html()最初null确实会。

原始代码有错误,应该是this.state.loaded而不是this.loaded

MyComponent extends React.Component {
  state = { loaded: false };

  componentDidMount() {
    this.props.fetchData.then(() => {
          this.setState({ loaded: true });
    });
  }

  methodThatIWantToTest() {
      //do some stuff here
  }

  render() {
      if (this.state.loaded) {
          return <p>hi</p>;
      } else {
          return null;
      }
  }
}

componentDidMountmethodThatIWantToTest最好考虑不同的单位。它们属于不同的测试。如果methodThatIWantToTest在生命周期钩子中被调用,它可能会在componentDidMount测试中被存根:

   it('should fetch data', async () => {
      const props = { fetchData: Promise.resolve('data') };
      const shallowWrapper = shallow(<MyComponent {...props}/>);
      expect(shallowWrapper.html()).toBe(null);
      await props.fetchData;
      expect(shallowWrapper.html()).toBe('<p>hi</p>');
   });

然后可以单独测试该方法。可以禁用生命周期挂钩以减少移动部件的数量:

   it('should do some stuff', () => {
      const shallowWrapper = shallow(<MyComponent {...props}/>, {disableLifecycleMethods: true});
      const result = shallowWrapper.instance().methodThatIWantToTest();
      expect(result).toBe(...);    
   });

推荐阅读