首页 > 解决方案 > Sinon.spy() & jest.spyOn - TypeError: Attempted to wrap undefined property getTableData as function

问题描述

Im trying to spy the "getTableData" method or any other class component method using jest "spyOn" or sinon "spy". All the time getting:

Cannot spy the getTableData property because it is not a function; undefined given instead with jest spyOn and

TypeError: Attempted to wrap undefined property getTableData as function with sinon spy.

Also the component which method Im testing is wrapped by HOC component, which is using redux connect. Then I tried to export it without HOC but test still not working with the same error

Note that const spy = jest.spyOn(wrapper.instance(), "getTableData"); is working fine only with component exported without HOC!

What I've already tried:

const spy = sinon.spy(MonthlyProjectPlan.prototype, 'getTableData');

//const spy = jest.spyOn(MonthlyProjectPlan.prototype, 'getTableData');

    const wrapper = mount(
      //<Provider store={store}>
            <MonthlyProjectPlan {...propsPanel} />
      //</Provider>
    );
export class MonthlyProjectPlan extends React.Component {
  groupBy = (list, keyGetter) => {
    //some secret magic
  };

  getTableData = () => {
    let result = [];
    if (this.props.data) {
      let groupedData = this.groupBy(this.props.data, item => item.commodity);
      // magic
    }
    return result
  };

  getTableColumns = () => {
    let tableData = this.getTableData();
    let columns = [
      {Header: 'Commodities', accessor: 'commodity', width: 300}
    ];

    if (tableData.length > 0) {
      let months = tableData[0].data.map(item => item.year_month_date);
      let monthsColumns = months.map((item, key) => {
        //magic
      });
      columns.push(...monthsColumns)
    }
    return columns
  };

  render() {
    if (!this.props.data)
      return (<LoadingBar/>);
    if (this.props.data.length < 1)
      return (<NoData/>);

    return (
      <div>
        <ReactTable data={this.getTableData()}
                    className="monthly-pipeline__table"
                    columns={this.getTableColumns()}
                    defaultSorted={[{id: "commodity", desc: false}]}
                    showPageSizeOptions={false}
                    showPagination={false}
                    minRows={false}/>

        <div className="monthly-pipeline-help">
          <div className="monthly-pipeline-help__title">
            Monthly Pipeline Shortfalls Percent
          </div>

          <table className="monthly-pipeline-help__table">
            <tbody>
            <tr>
              <td style={{backgroundColor: colors.darkGreen}}>0% - 25%</td>
              <td style={{backgroundColor: colors.yellow}}>26% - 50%</td>
              <td style={{backgroundColor: colors.orange}}>51% - 75%</td>
              <td style={{backgroundColor: colors.red}}>76% - 100%</td>
            </tr>
            </tbody>
          </table>

        </div>
      </div>
    )
  }
}

export default Panel(MonthlyProjectPlan)

Test below is not working

it("should render MonthlyProjectPlan Global component correctly", () => {
    const spy = sinon.spy(MonthlyProjectPlan.prototype, 'getTableData');
    //const spy = jest.spyOn(MonthlyProjectPlan.prototype, 'getTableData');
    const wrapper = mount(
      //<Provider store={store}>
      <MonthlyProjectPlan {...propsPanel} />
      //</Provider>
    );

errors:

"Cannot spy the getTableData property because it is not a function; undefined given instead" with jest spyOn

and

"TypeError: Attempted to wrap undefined property getTableData as function" with sinon spy.

This is working fine, but only with component exported without HOC

  it("should render MonthlyProjectPlan Global component correctly", () => {
    const wrapper = mount(
      //<Provider store={store}>
      <MonthlyProjectPlan {...propsPanel} />
      //</Provider>
    );
    // const spy = jest.spyOn(wrapper.instance(), "getTableData");
    // wrapper.instance().forceUpdate();
    // expect(spy).toHaveBeenCalled();
    // expect(spy.mock.calls.length).toBe(5);

标签: javascriptreactjsreduxjestjsenzyme

解决方案


您将getTableData方法定义为类属性。因此,原型中没有定义该方法。相反,它是您创建的实例的属性。

这意味着代码(您提供的代码的简化版本):

export class MonthlyProjectPlan {
    getTableData = () => {
        let result = [];
        if (this.props.data) {
            let groupedData = this.groupBy(this.props.data, item => item.commodity);
            // magic
        }
        return result
    };

    render() {

    }
}

是相同的:

function MonthlyProjectPlan() {
    this.getTableData = function() {
        let result = [];
        if (this.props.data) {
            let groupedData = this.groupBy(this.props.data, item => item.commodity);
            // magic
        }
        return result
    };
}

MonthlyProjectPlan.prototype.render = function() {};

请注意,getTableData方法未在MonthlyProjectPlan类的原型中定义,而是在您创建的类的每个实例上创建一个新方法。

正因为如此,它MonthlyProjectPlan.prototype.getTableData是未定义的,你不能窥探它。


推荐阅读