15

我正在开发一个包装器组件,用于在 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间谍的调用计数。这是测试的相应代码:

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>);

    }}

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

4

2 回答 2

17

可以不依赖sinon. 通过期望调用onLoadandonFire事件侦听器,测试检查是否img触发了loadanderror事件。

相反,simulate img's 事件使用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对组件的需要。更新的测试可以在这里找到。

于 2016-11-24T22:05:28.257 回答
0

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

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

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

于 2019-09-22T16:03:37.953 回答