【问题标题】:Enzyme does not reflect state update [duplicate]酶不反映状态更新[重复]
【发布时间】:2019-05-03 20:20:04
【问题描述】:

我正在为连接到 Redux 存储的 React 组件编写测试。我要测试的是,当我在 store 上 dispatch reset 时,组件状态恢复为默认值。

思路如下:当RESET被派发时,组件接收到truthy reset属性,并在componentWillReceiveProps中将组件状态设置为默认值。它可以工作,但它没有通过测试。如果我连接调试器并运行测试,我可以看到它在componentWillReceiveProps 中设置状态,但是当我期望timeLeft 状态为 10000 时,它仍然是上面设置的 1111。我错过了什么?这可能不是一个完美的测试方式,但我对 React/Redux 组件测试有点陌生,很高兴听到改进我测试方式的最佳实践。

减速机:

const resetReducer = (state, action) => (action.type === 'RESET');

组件:

class Timer extends React.Component {
  componentWillReceiveProps(next) {
    if (next.reset) {
      this.setState({
        timeLeft: 10000,
      });
    }
}

function mapStateToProps(state) {
  return {
    reset: state.reset
  }
}

export default connect(mapStateToProps)(Timer);

测试:

it('Reset', () => {
    // use mount because I need componentWillReceiveProps to run
    const wrapper = mount(<Timer/>);

    wrapper.setState({
      timeLeft: 1111
    });

    store.dispatch({ type: 'RESET' });
    wrapper.update();

    expect(wrapper.state('timeLeft)).toBe(10000);
});

【问题讨论】:

    标签: reactjs unit-testing redux react-redux enzyme


    【解决方案1】:

    您无需测试 Redux 功能。您应该隔离并测试您的 React 代码是否正常工作。

    改变这一行

    class Timer extends React.Component {
    

    export class Timer extends React.Component {
    

    在你的测试文件中

    import { Timer } from './file-location';
    

    你可以像这样测试你的组件行为

    it('Reset', () => {
      const wrapper = mount(<Timer reset={false}/>);
    
      wrapper.setState({
        timeLeft: 1111
      });
      wrapper.update();
      expect(wrapper.state().timeLeft).toBe(1111);
    
      wrapper.setProps({ reset: true});
      wrapper.update();
      expect(wrapper.state().timeLeft).toBe(10000);
    });
    

    【讨论】:

      【解决方案2】:

      Enzyme 不允许您在编写单元测试时进行这种测试,因为使用 mountshallow 您正在隔离组件。不再是connected 组件了。

      这就是为什么即使您调用“RESET”操作,组件也不会收到更改。

      您可以做些什么来测试组件是否在道具正确时更新,您可以像这样更新道具:

       wrapper.setProps({ timeLeft: 10000});
      

      这样,您可以强制组件接收道具并检查行为是否符合您的预期。

      it('Reset', () => {
          // use mount because I need componentWillReceiveProps to run
          const wrapper = mount(<Timer/>);
      
          wrapper.setState({
            timeLeft: 1111
          });
      
          wrapper.setProps({ timeLeft: 10000});
          wrapper.update();
      
          expect(wrapper.state('timeLeft)).toBe(10000);
      });
      

      然后,要测试 Reducer,您可以按照官方文档:https://github.com/reduxjs/redux/blob/master/docs/recipes/WritingTests.md

      请记住,单元测试的想法是将所有内容隔离并拆分为代码的小部分。 如果您想测试组件之间的集成,请尝试使用 Automation Tets。

      希望这对你有用!

      【讨论】:

      • 谢谢。有一件事,在这种情况下,将 reset 而不是 timeLeft 传递给 props 并查看它是否按预期改变状态更有意义。然后,我想知道当我调度 RESET 动作时,reducer 是否正确设置了重置,以及重置按钮是否调度了这些动作,但这些与该组件无关。
      猜你喜欢
      • 1970-01-01
      • 2023-02-13
      • 1970-01-01
      • 1970-01-01
      • 2020-11-03
      • 2022-01-17
      • 2018-04-08
      • 2013-01-02
      • 1970-01-01
      相关资源
      最近更新 更多