前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[译] 更可靠的 React 组件:从"可测试的"到"测试通过的"

[译] 更可靠的 React 组件:从"可测试的"到"测试通过的"

作者头像
江米小枣
发布2020-06-15 22:14:30
9630
发布2020-06-15 22:14:30
举报
文章被收录于专栏:云前端

原文摘自:https://dmitripavlutin.com/7-architectural-attributes-of-a-reliable-react-component/#6testableandtested

一个被验证过针对给定的输入会渲染出符合期望的输出的组件,称为 测试过的(tested) 组件; 一个 可测试的(testable) 组件意味着其易于测试

如何确保一个组件如期望的工作呢?你可以说:“我都自己手动试过的呀。”

如果你打算对每个组件的每个改动都手动验证的话,或早或晚的,你就会跳过这项苦差事了,而小的瑕疵早晚也会出现。

这就是对组件的自动化验证,也就是单元测试(unit test),为何重要的原因。单元测试保证了每次对组件做出的更改后,组件都能正确工作。

单元测试并不只与早期发现 bug 有关。另一个重要的方面是用其检验组件架构化水平优劣的能力。

我觉得这句话格外的重要:

一个 无法测试难以测试 的组件,基本上就等同于 设计得很拙劣 的组件.

组件之所以难以测试时因为其有太多的 props、依赖、引用的模型和对全局变量的访问 -- 这都是不良设计的标志。

一个架构设计羸弱的组件,就会变成无法测试的,进而你就会简单的跳过单元测试,又导致了其保持未测试状态,这是一个恶性循环。

总之,许多应用为何是未测试状态的原因就是不良的组件设计。即便你想动手测试,也无处下手。

案例学习:可测试就意味着设计良好

之前的文章中提及过 <Controls> 组件。

下面的代码测试了高度依赖于父组件结构的 <Controls> 版本:

代码语言:javascript
复制
import assert from 'assert';  
import { shallow } from 'enzyme';

class Controls extends Component {  
  render() {
    return (
      <div className="controls">
        <button onClick={() => this.updateNumber(+1)}>
          Increase
        </button> 
        <button onClick={() => this.updateNumber(-1)}>
          Decrease
        </button>
      </div>
    );
  }
  updateNumber(toAdd) {
    this.props.parent.setState(prevState => ({
      number: prevState.number + toAdd       
    }));
  }
}

class Temp extends Component {  
  constructor(props) {
    super(props);
    this.state = { number: 0 };
  }
  render() {
    return null;
  }
}

describe('<Controls />', function() {  
  it('should update parent state', function() {
    const parent = shallow(<Temp/>);
    const wrapper = shallow(<Controls parent={parent} />);

    assert(parent.state('number') === 0);

    wrapper.find('button').at(0).simulate('click');
    assert(parent.state('number') === 1);

    wrapper.find('button').at(1).simulate('click');
    assert(parent.state('number') === 0); 
  });
});

<Controls> 测试起来非常复杂,因为它关联了父组件的实现细节。

测试场景中需要一个额外的 <Temp> 组件,用来模拟父组件,检验 <Controls> 是否正确修改了父组件的状态。

<Controls> 独立于父组件的细节时,测试就简单了。让我们测试一下合理封装版本的 <Controls> 组件:

代码语言:javascript
复制
import assert from 'assert';  
import { shallow } from 'enzyme';  
import { spy } from 'sinon';

function Controls({ onIncrease, onDecrease }) {  
  return (
    <div className="controls">
      <button onClick={onIncrease}>Increase</button> 
      <button onClick={onDecrease}>Decrease</button>
    </div>
  );
}

describe('<Controls />', function() {  
  it('should execute callback on buttons click', function() {
    const increase = sinon.spy();
    const descrease = sinon.spy();
    const wrapper = shallow(
      <Controls onIncrease={increase} onDecrease={descrease} />
    );

    wrapper.find('button').at(0).simulate('click');
    assert(increase.calledOnce);
    wrapper.find('button').at(1).simulate('click');
    assert(descrease.calledOnce);
  });
});

封装好则测试易,反之不恰当的封装让测试变得困难。

可测试性是一个检验组件结构良好程度的实践标准。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-06-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 云前端 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 案例学习:可测试就意味着设计良好
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档