在我的测试套件中,如何对类的属性存根,即函数*?对于普通方法,使用Object.getOwnPropertyNames(component.prototype)和猴子修补每个找到的方法很容易,但是经过长时间的努力,我没有找到任何方法来提取通过分配给类的字段而创建的函数。

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

转译的问题在于,箭头功能属性(当然是按预期的方式)分配给输出转译的“类”(当然实际上是功能)的实例。因此,除了实例化此对象外,我看不到其他任何对它们进行存根的方法,对吗? Here is the example of input es7 code and the babel's output.但是我并不特别喜欢这种解决方案,看起来很hacky。该解决方案的另一个缺点是,我无法直接实例化组件的类。



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

最佳答案

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

语境

这是一个React组件的示例,该组件具有使用粗箭头符号定义的方法handleClick

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进行存根处理,以便仅测试所需的单元。但是现在您遇到了一个问题,因为您只能在实例化后访问handleClick,并且componentWillMount方法将在其实例化生命周期中被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类进行属性测试。

07-26 06:45