美文网首页
React 单元测试

React 单元测试

作者: 风之化身呀 | 来源:发表于2018-06-18 13:33 被阅读180次

    1、Mocha测试扫盲

    a、测试脚本里面应该包括一个或多个describe块,每个describe块应该包括一个或多个it块。

    // add.js
    function add(x, y) {
      return x + y;
    }
    module.exports = add;
    
    // add.test.js
    var add = require('./add.js');
    var expect = require('chai').expect;       // 引入断言库 chai , Mocha本身不提供(Mocha并不限制使用哪一种断言库)
    
    describe('加法函数的测试', function() {
      it('1 加 1 应该等于 2', function() {
        expect(add(1, 1)).to.be.equal(2);
      });
    });
    

    b、describe块称为"测试套件"(test suite),表示一组相关的测试。它是一个函数,第一个参数是测试套件的名称("加法函数的测试"),第二个参数是一个实际执行的函数。
    c、it块称为"测试用例"(test case),表示一个单独的测试,是测试的最小单位。它也是一个函数,第一个参数是测试用例的名称("1 加 1 应该等于 2"),第二个参数是一个实际执行的函数。
    d、expect断言的写法都是一样的。头部是expect方法,尾部是断言方法,比如equal、a/an、ok、match等。两者之间使用to或to.be连接。

    // 相等或不相等
    expect(4 + 5).to.be.equal(9);
    expect(4 + 5).to.be.not.equal(10);
    expect(foo).to.be.deep.equal({ bar: 'baz' });
    
    // 布尔值为true
    expect('everthing').to.be.ok;
    expect(false).to.not.be.ok;
    
    // typeof
    expect('test').to.be.a('string');
    expect({ foo: 'bar' }).to.be.an('object');
    expect(foo).to.be.an.instanceof(Foo);
    
    // include
    expect([1,2,3]).to.include(2);
    expect('foobar').to.contain('foo');
    expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo');
    
    // empty
    expect([]).to.be.empty;
    expect('').to.be.empty;
    expect({}).to.be.empty;
    
    // match
    expect('foobar').to.match(/^foo/);
    

    e、mocha --recursive 命令会执行test目录下的所有test测试脚本
    f、异步测试:Mocha默认每个测试用例最多执行2000毫秒,如果到时没有得到结果,就报错。对于涉及异步操作的测试用例,这个时间往往是不够的,需要用-t或--timeout参数指定超时门槛(mocha -t 5000 timeout.test.js)
    g、Mocha内置对Promise的支持,允许直接返回Promise,等到它的状态改变,再执行断言,而不用显式调用done方法

    it('异步请求应该返回一个对象', function() {
      return fetch('https://api.github.com')
        .then(function(res) {
          return res.json();
        }).then(function(json) {
          expect(json).to.be.an('object');
        });
    });
    

    h、大型项目有很多测试用例。有时,我们希望只运行其中的几个,这时可以用only方法。describe块和it块都允许调用only方法,表示只运行某个测试套件或测试用例。

    it.only('1 加 1 应该等于 2', function() {
      expect(add(1, 1)).to.be.equal(2);
    });
    

    2、React 单元测试

    a、一个React组件有两种存在形式:虚拟DOM对象(即React.Component的实例)和真实DOM节点。官方测试工具库对这两种形式,都提供测试解决方案。

    Shallow Rendering:测试虚拟DOM的方法(将一个组件渲染成虚拟DOM对象,但是只渲染第一层,不渲染所有子组件)
    DOM Rendering: 测试真实DOM的方法
    

    b、Enzyme库:官方测试工具库的封装,它模拟了jQuery的API,非常直观

    // 1、shallow
    import {shallow} from 'enzyme';
    
    describe('Enzyme Shallow', function () {
      it('App\'s title should be Todos', function () {
        let app = shallow(<App/>);
        expect(app.find('h1').text()).to.equal('Todos');
      });
    };
    
    // 2、render(将React组件渲染成静态的HTML字符串,然后分析这段HTML代码的结构,返回一个对象)
    // 适用于依赖类名做测试
    import {render} from 'enzyme';
    
    describe('Enzyme Render', function () {
      it('Todo item should not have todo-done class', function () {
        let app = render(<App/>);
        expect(app.find('.todo-done').length).to.equal(0);
      });
    });
    
    // 3、mount(将React组件加载为真实DOM节点,要求存在一个真实的DOM环境,否则会报错。因此,测试用例之中,DOM环境(即window, document 和 navigator 对象)必须是存在的,[jsdom](https://github.com/tmpvar/jsdom) 库提供这项功能。)
    // 修改package.json的test字段如下:
    {
      "scripts": {
        "test": "mocha --compilers js:babel-core/register --require ./test/setup.js",
      },
    }
    
    // setup.js
    import jsdom from 'jsdom';
    if (typeof document === 'undefined') {
      global.document = jsdom.jsdom('<!doctype html><html><body></body></html>');
      global.window = document.defaultView;
      global.navigator = global.window.navigator;
    }
    
    //  test.js
    import {mount} from 'enzyme';
    
    describe('Enzyme Mount', function () {
      it('Delete Todo', function () {
        let app = mount(<App/>);
        let todoLength = app.find('li').length;
        app.find('button.delete').at(0).simulate('click');
        expect(app.find('li').length).to.equal(todoLength - 1);
      });
    });
    

    c、Enzyme的常用API

    .get(index):返回指定位置的子组件的DOM节点
    .at(index):返回指定位置的子组件
    .first():返回第一个子组件
    .last():返回最后一个子组件
    .type():返回当前组件的类型
    .text():返回当前组件的文本内容
    .html():返回当前组件的HTML代码形式
    .props():返回根组件的所有属性
    .prop(key):返回根组件的指定属性
    .state([key]):返回根组件的状态
    .setState(nextState):设置根组件的状态
    .setProps(nextProps):设置根组件的属性
    

    相关文章

      网友评论

          本文标题:React 单元测试

          本文链接:https://www.haomeiwen.com/subject/mklneftx.html