如何使用反应,玩笑和酶对自定义表格单元格渲染器功能进行单元测试?

问题描述 投票:0回答:1

我想测试一个返回JSX内容的React类组件函数。下面是我的代码:

产品组件

export default class Products extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      products: [],
    };
  }

  iconRenderer = (data) => {
    return (
      <i
        className="fa fa-qrcode fa-3x"
      >
      </i>
    );
  };

  getDisplayColumns = () => {
    return [
      {
        fieldName: 'producticon',
        displayText: 'Name',
        isEditable: false,
        visible: true,
        columnSize: 2,
        renderer: this.iconRenderer
      }
    ];
  };

  render() {
    const displayColumns = this.getDisplayColumns();
    return (
      <div className=''>
            {this.state.products && this.state.products.length > 0 &&
            <CustomTableGeneric
              tableId="item-list-table"
              data={this.state.products}
              columns={displayColumns}
            >
            </CustomTableGeneric>
            }
          </div>
    );
  }
}

CustomTableGeneric组件(我试图简化代码)

export default class CustomTableGeneric extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            currentTableData: [],
            columnsToDisplay: [],
        };

        this.renderRows = this.renderRows.bind(this);
        this.renderIndividualRow = this.renderIndividualRow.bind(this);
    }

    renderIndividualRow(data, dataKeys) {
        return dataKeys.map((item, index) => {
            let currentRowId = data['id'];
            let columnWidth = this.state.columnsToDisplay[index].columnSize;
            if (item.renderer) {
                    return (
                        <Col md={columnWidth} className="table-column-cell"
                             key={index}>
                            {item.renderer(data, item.fieldName)}
                        </Col>
                    );
                } else {
                    return (
                        <Col md={columnWidth} className="table-column-cell" key={index}>{data[item.fieldName]}</Col>
                    );
                }
        });
    }

    renderRows() {
        let dataKeys = clonedeep(this.state.columnsToDisplay);
        let dataRows = clonedeep(this.state.currentTableData);
        if (dataRows.length > 0) {
            return dataRows.map((row, index) => {
                return (
                        <Row key={index} className="table-row">
                            {this.renderIndividualRow(row, dataKeys)}
                        </Row>
                    );
            });
        }
    }

    render() {
        return (
            <Row id={this.props.tableId}>
                <Col className="custom-table">
                    <Row className="table-header">
                        {this.renderHeaders()}
                    </Row>
                    {this.renderRows()}
                </Col>
            </Row>
        );
    }
}

CustomTableGeneric.propTypes = {
    tableId: PropTypes.string,
    data: PropTypes.arrayOf(PropTypes.object).isRequired,
    columns: PropTypes.arrayOf(PropTypes.shape({
        fieldName: PropTypes.string,
        displayText: PropTypes.string,
        renderer: PropTypes.func,
    })).isRequired,
};

Products.test.js

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

import CustomTableGeneric from '../../components/CustomTableGeneric';
import Products from './Products';

const props = {
  id: '123'
};

describe('Products function tests', () => {
  it('should call the iconRenderer function', () => {
    const wrapper = shallow(<Products {...props} />);
    const result = wrapper
        .instance()
        .iconRenderer();
    console.log(result);

  });
});

和下面是我运行测试时的控制台输出。

{ '$$typeof': Symbol(react.element),
      type: 'i',
      key: null,
      ref: null,
      props: { className: 'fa fa-qrcode fa-3x' },
      _owner: null,
      _store: {} }

如您所见,如果我从测试中显式调用iconRenderer(),它正在执行。但是我要测试的是检查呈现[[Products组件时是否调用了iconRenderer()。请查看我在render函数中如何调用它,例如产品render()-> getDisplayColumns()-> CustomTableGeneric()-> iconRenderer()。

下面是我要运行的实际测试

describe('Products function tests', () => { it('should call the iconRenderer function', () => { const wrapper = shallow(<Products {...props} />); jest.spyOn(wrapper.instance(), 'iconRenderer'); expect(wrapper.instance().iconRenderer()).toHaveBeenCalled(); }); });

但是我遇到了错误

Error: expect(jest.fn())[.not].toHaveBeenCalled() jest.fn() value must be a mock function or spy. Received: object: <i className="fa fa-qrcode fa-3x" />

任何建议都值得赞赏。
reactjs unit-testing jestjs enzyme
1个回答
0
投票
据我所见,您的代码有两个问题:

  1. 您无意中调用了expect中的模拟函数,这会导致错误:expect正在接收模拟iconRenderer的返回值,而不是模拟本身。将您的expect行更改为:

    expect(wrapper.instance().iconRenderer).toHaveBeenCalled();

  2. 您需要在渲染iconRenderer之前模拟Product,因此在渲染Product时会调用它。因此,需要在此行之前对其进行嘲笑:

    const wrapper = shallow(<Products {...props} />);

    您可以在this question中看到有关此操作的示例。
© www.soinside.com 2019 - 2024. All rights reserved.