测试开玩笑的模拟事件回调的返回值

时间:2018-08-01 03:47:02

标签: reactjs jestjs enzyme

我在Button.tsx中具有以下组件:

// Button.tsx
import * as React from 'react';
import { Button as ReactstrapButton } from 'reactstrap';

interface IHandlerParams<onClickArgsType> {
  onClickParams?: onClickArgsType
}

export interface IButtonProps<onClickArgsType = {}> {
  color?: string,
  onClick?: (event: React.MouseEvent<any>, args?: onClickArgsType) => any,
  handlersParams?: IHandlerParams<onClickArgsType>
}

interface IHandlers {
  onClick: React.MouseEventHandler<any>
}

export class Button<onClickArgsType> extends React.Component<IButtonProps<onClickArgsType>> {

  private handlers: IHandlers;

  constructor(props: IButtonProps<onClickArgsType>) {
    super(props);
    this.handlers = {
      onClick: (MouseEvent:React.MouseEvent<any>) => { if (this.props.onClick) {this.props.onClick( MouseEvent, this.props.handlersParams ? this.props.handlersParams.onClickParams : undefined) }}
    }
  }

  render() {
    return (
      <ReactstrapButton
        color={this.props.color}
        onClick={this.handlers.onClick}>
        {this.props.children}
      </ReactstrapButton>
    )
  }
}

注意: :我正在使用该奇怪的“ handlers”对象来管理事件的回调,因此我在ReactstrapButton属性中没有直接的箭头功能,避免了每次创建一个新对象,从而防止重新渲染该组件。

以及Button.unit.test.tsx中的相应测试文件:

// Button.unit.test.tsx
import { mount, shallow } from "enzyme";
import * as React from "react";

import { Button, IButtonProps } from "./Button";

interface IOnClickParamsTest {
  a: number,
  b: number
}

describe('App component', () => {
  it('renders without crashing', () => {
    shallow(
      <Button />
    );
  });

  it('test the onClick method', () => {
    const onClick = jest.fn((event: React.MouseEvent<IButtonProps<IOnClickParamsTest>>, params: IOnClickParamsTest) => params.a + params.b);
    const onClickParams: IOnClickParamsTest = { a: 4, b: 5 };

    const buttonComponent = mount(
      <Button<IOnClickParamsTest>
        onClick={onClick}
        handlersParams={{ onClickParams }}
      />
    );
    buttonComponent.simulate("click");

    expect(onClick).toBeCalled();
    expect(onClick.mock.calls[0][1]).toBe(onClickParams);// The second argument of the first call to the function was onClickParams
    // expect(onClick.mock.results[0].value).toBe(9);// The return value of the first call to the function was 9
  });

});

测试按预期通过,但在最后注释的行中失败,并显示以下错误:

TypeError: Cannot read property '0' of undefined

该错误引用了onClick.mock.results属性。我已经调试了onClick.mock属性,结果当然不存在。但是,按照Jest中的this docs,其中应该存在一个results属性。

顺便说一句,我正在使用:

"react": "^16.4.0",
"react-dom": "^16.4.0",

"enzyme": "^3.3.0",
"enzyme-adapter-react-16": "^1.1.1",
"jest": "^23.1.0",
"jest-enzyme": "^6.0.2",
"ts-jest": "^22.4.6"

有什么想法吗?提前非常感谢您!

1 个答案:

答案 0 :(得分:1)

Jest v23中提供了返回值。截至今天(2018年8月1日),已使用带有react-scripts-ts的create-react-app引导的应用程序正在使用Jest v22。 create-react-app将在不久的将来更新为使用Jest v23。

同时,可以使用Sinon fakes测试返回值。

在这种情况下,更新的测试如下:

// Button.unit.test.tsx
import { mount, shallow } from "enzyme";
import * as React from "react";
import * as sinon from 'sinon';

import { Button, IButtonProps } from "./Button";

interface IOnClickParamsTest {
  a: number,
  b: number
}

describe('App component', () => {
  it('renders without crashing', () => {
    shallow(
      <Button />
    );
  });

  it('test the onClick method', () => {
    const onClick = sinon.fake((event: React.MouseEvent<IButtonProps<IOnClickParamsTest>>, params: IOnClickParamsTest) => params.a + params.b);
    const onClickParams: IOnClickParamsTest = { a: 4, b: 5 };

    const buttonComponent = mount(
      <Button<IOnClickParamsTest>
        onClick={onClick}
        handlersParams={{ onClickParams }}
      />
    );
    buttonComponent.simulate("click");

    expect(onClick.calledOnce).toBe(true);
    expect(onClick.firstCall.args[1]).toBe(onClickParams);
    expect(onClick.returnValues[0]).toBe(9);
  });

});