Sinon.spy()&jest.spyOn-TypeError:尝试将未定义的属性getTableData包装为函数

时间:2019-04-16 13:01:27

标签: javascript reactjs redux jestjs enzyme

我正在尝试使用玩笑“ spyOn”或sinon“ spy”来监视“ getTableData”方法或任何其他类组件方法。一直在获取:

Cannot spy the getTableData property because it is not a function; undefined given instead,带有开玩笑的spyOn和

TypeError: Attempted to wrap undefined property getTableData as function和sinon间谍。

Im测试方法的组件也由使用redux connect的HOC组件包装。然后我尝试不使用HOC导出它,但是测试仍然无法解决相同的错误

请注意,const spy = jest.spyOn(wrapper.instance(), "getTableData");仅适用于不带HOC导出的组件!

我已经尝试过的:

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)

下面的测试不起作用

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>
    );

错误:

  

“无法监视getTableData属性,因为它不是函数;取而代之的是未定义”

  

“ TypeError:尝试将未定义的属性getTableData封装为函数”与sinon间谍。

这工作正常,但仅适用于没有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);

1 个答案:

答案 0 :(得分:0)

您正在将 getTableData 方法定义为class property。因此,该方法未在原型中定义。相反,它是您创建的实例的属性。

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

    @foreach($getList as $campaign)
    <div id="expire_campaign_modal{{$campaign->campaign_id}}" class="uk-modal">
        <div class="uk-modal-dialog" style="width:30%;">
            <a class="uk-modal-close uk-close"></a>
            <div class="uk-grid">
                <div class="uk-width-1-1">
                    <div class="md-card">
                        <div class="md-card-content" style="text-align: center;">
                            <div style="display:flex; justify-content:center; align-items:baseline;">
                                <h2 class="campaign_id">{{$campaign->campaign_id}} - </h2>
                                <h2 style="margin-left: 10px;"> {{$campaign->campaign_name}}</h2>
                            </div>
                            <h3>Are you sure you want to expire this campaign?</h3>
                            <button class="uk-button uk-button-primary expire-campaign">Expire</button>
                            <button class="uk-button uk-button-default uk-modal-close">Cancel</button>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    @endforeach

    $(".expire-campaign").click(function(e){

        e.preventDefault();

        var campaign_id = document.querySelector(".campaign_id").textContent;

        console.log(campaign_id);

    });

与以下相同:

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

    render() {

    }
}

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

>

因此,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() {}; 是未定义的,您无法对其进行监视。