ES7

时间:2016-01-26 17:18:49

标签: javascript unit-testing reactjs stubbing ecmascript-7

在我的测试套件中,如何存储一个类'属性,这是一个函数*?使用常规方法可以很容易地使用Object.getOwnPropertyNames(component.prototype)和猴子修补每个找到的方法,但之后经过长时间的斗争,我没有找到任何方法来提取通过分配给类'字段创建的函数。

我的测试堆栈包括Jest with Jasmine2和babel。

转换的问题是 arrow-function-properties (当然是预期的)分配给输出的实例转换为“class”(当然实际上是函数)。所以我没有看到任何方法将它们存在,然后实例化这个对象,我是对的吗? Here is the example of input es7 code and the babel's output.但是我并不特别喜欢这个解决方案,看起来非常h​​acky。此解决方案的另一个缺点是我无法直接实例化组件的类。

(*)这个问题的背景是单元测试React组件用类似es7的类编写,箭头函数分配给类的属性以便自动绑定。

2 个答案:

答案 0 :(得分:2)

我在为我正在工作的项目编写单元测试时遇到了同样的问题,我认为我有一个好的模式来解决它。希望它有所帮助:

上下文

以下是使用胖箭头表示法定义方法handleClick的React组件的示例。

import React, { Component } from 'react';

class Foo extends Component {
  componentWillMount() {
    this.handleClick();
  }

  handleClick = (evt) => {
    // code to handle click event...
  }

  render() {
    return (
      <a href="#" onClick={this.handleClick}>some foo link</a>
    );
  }
}

问题

如此link Babel 中所述,将转换代码,以便handleClick方法仅在实例化后可用(检查第31至33行生成的构造函数>

这里的问题是,有时您需要在实例化类之前访问使用胖箭头表示法定义的方法。

让我们举例来说,您正在编写componentWillMount类方法的单元测试,并且您希望存根handleClick,以便您只测试所需的单位。但是现在你遇到了问题,因为在实例化之后你只能访问handleClickcomponentWillMount方法将由React自动调用,作为其实例化生命周期的一部分。

解决方案

以下是我如何应用一个简单的模式来解决这样的问题:

import React from 'react';
import { mount } from 'enzyme';
import { expect } from 'chai';
import sinon from 'sinon';

import Foo from './foo';

describe('Foo', () => {
  describe('componentWillMount method', () => {
    const handleClickStub = sinon.stub();
    class FooWrapper extends Foo {
      constructor(props) {
        super(props);
        this.handleClick = handleClickStub;
      }
    }

    it('should register a click event listener to the externalElement property', () => {
      handleClickStub.reset();
      mount(<FooWrapper />);
      expect(handleClickStub.calledOnce).to.be.true;
    });
  });
});

解释

在初始化原始组件后,我已将原始Foo组件包装到FooWrapper其构造函数的位置我将原始handleClick方法替换为存根版本,允许我属性测试我的componentWillMount类。

答案 1 :(得分:1)

由于babel通过transform-class-properties在类方法上转换箭头函数语法的方式,类方法不再绑定在原型上,而是绑定到实例。

使用Jest 19的内置断言和.spyOn方法,这是我的解决方案:

import React from 'react';
import { shallow } from 'enzyme';

describe('MyComponent', () => {
  it('should spy properly', () => {
    const wrapper = shallow(<Component />);
    const wrapperInstance = wrapper.instance();
    const spy = jest.spyOn(wrapperInstance, 'functionName');
    wrapperInstance.functionName();
    expect(spy).toHaveBeenCalledTimes(1);
  })
});