【问题标题】:Testing changes to React component state and spying on instance methods using enzyme测试对 React 组件状态的更改并使用酶监视实例方法
【发布时间】:2019-09-23 00:03:37
【问题描述】:

我正在开发一个用于在 React 中平滑加载图像的包装器组件。我将酶与 mocha、chai 和 sinon 一起使用来对我的组件进行单元测试。在这里的测试中,我试图测试:

  1. 图片加载后组件状态更新

  2. 组件上的onLoad实例方法被调用

const wrapper = shallow( ); 常量 onLoad = wrapper.find('img').props().onLoad; 常量 onLoadSpy = sinon.spy(onLoad);包装器.更新(); 常量状态 = wrapper.state().status; 期望(onLoadSpy).to.have.been.call; 期望(状态).to.equal('加载');

我发现无论是酶还是onLoad spy 的调用计数都没有反映状态的更新。这是对应的测试代码:

export default class Image extends Component {
  constructor(props) {
    super(props);
    if (props.src != null && typeof props.src === 'string') {
      this.state = {
        status: LOADING,
      };
    } else {
      this.state = {
        status: PENDING,
      };
    }
    this.onLoad = this.onLoad.bind(this);
  }

  onLoad() {
    this.setState({
      status: LOADED,
    });
  }

  render() {
    //lots of code above the part we care about
    const defaultImageStyle = style({
      opacity: 0,
      transisition: 'opacity 150ms ease',
    });

    const loadedImageStyle = style({
      opacity: 1,
    });

    let imageStyle = defaultImageStyle;

    if (this.state.status === LOADED) {
      imageStyle = merge(defaultImageStyle, loadedImageStyle);
    } else {
      imageStyle = defaultImageStyle;
    }


    let image;
    if (alt != null) {
      image = (<img
        className={imageStyle}
        src={src}
        width={width}
        height={height}
        alt={alt}
        onLoad={this.onLoad}
      />);
    } else {
      image = (<img
        className={imageStyle}
        src={src}
        width={width}
        height={height}
        role="presentation"
        onLoad={this.onLoad}
      />);
    }

    let statusIndicator = null;
    if (this.state.status === LOADING) {
      statusIndicator = (<div className={loadingStyle}></div>);
    }

    return (<div className={wrapperStyle}>
      {statusIndicator}
      {image}
    </div>);

    }}

查看完整代码以获得更好的上下文:

【问题讨论】:

    标签: javascript reactjs sinon enzyme chai-enzyme


    【解决方案1】:

    无需依赖sinon 即可进行测试。通过期望调用onLoadonFire 事件侦听器,测试检查img 是否触发loaderror 事件。

    相反,simulate img 的事件使用 enzyme 并检查是否发生了适当的状态转换:

    it('has a state of LOADED if a good src prop is supplied', () => {
      const wrapper = shallow(<Image 
        src="anyString.jpg"
        width={300}
        height={300}
      />);
    
      const img = wrapper.find('img');
      img.simulate('load');
      const status = wrapper.state().status;
      expect(status).to.equal('LOADED');
    });
    

    这也消除了mount 组件的需要。更新的测试可以在here找到。

    【讨论】:

    • 如果onLoad函数返回一个promise怎么办?这在这种情况下不起作用。
    • @saran3h 不是一个详细的答案:考虑使用 jest 来模拟您在 onLoad 中收到承诺的函数。如果这是外部库的一部分或直接在函数内部,我建议将其提取到可以模拟的函数或方法中。
    【解决方案2】:

    我看到这种方法的主要问题是状态是一个内部的东西,而不是应该在组件之外知道的东西。现在您将状态信息(在本例中为“状态”)泄漏到测试中。

    这样做意味着您没有进行“黑盒测试”,这是最有价值的测试类型。您正在泄漏组件的实现细节。换句话说,应该高度考虑“封装”。

    也许有更好的方法来测试它。例如,您也可以导出一个展示组件,它将您需要测试的状态部分作为道具。或者使用酶find 方法查找状态为“已加载”时将呈现的元素。

    【讨论】:

      猜你喜欢
      • 2018-06-21
      • 1970-01-01
      • 2017-11-26
      • 2019-03-13
      • 1970-01-01
      • 2016-08-20
      • 1970-01-01
      • 2017-07-03
      • 2019-03-05
      相关资源
      最近更新 更多