在 Jest 中测试 onChange 函数

新手上路,请多包涵

我对 Jest 和一般测试比较陌生。我有一个带有输入元素的组件:

 import * as React from "react";

export interface inputProps{
    placeholder: string;
    className: string;
    value: string;
    onSearch: (depID: string) => void;
}

onSearch(event: any){
    event.preventDefault();
    //the actual onclick event is in another Component
    this.props.onSearch(event.target.value.trim());
}

export class InputBox extends React.Component<inputProps, searchState> {
  render() {
        return (
            <input
                onChange={this.onSearch} //need to test this
                className={this.props.className}
                type="text"
                value={this.props.value}
                placeholder={this.props.placeholder} />
        );
    }
}

我想要一个测试来检查输入元素的 onChange 是一个将输入元素的 value 属性作为参数的函数。这是我到目前为止已经走了多远:

 //test to see the input element's onchange
//returns a function that takes its value as a param
it("onChange param is the same value as the input value", () => {
    const mockFn = jest.fn();
    const input = enzyme.shallow(<InputBox
                                    value="TestVal"
                                    placeholder=""
                                    className=""
                                    onSearch={mockFn}/>);

       input.find('input').simulate('change',  { preventDefault() {} });
       expect(mockFn.mock.calls).toBe("TestVal");
    });

我要离开这里的第一个解决方案 模拟 Jest 中的按钮单击 并且: https ://facebook.github.io/jest/docs/en/mock-functions.html

编辑:运行上面会引发以下错误:

  TypeError: Cannot read property 'value' of undefined

原文由 blankface 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.4k
2 个回答

我认为您的代码片段的语法应该是:

 import React from 'react';

export default class InputBox extends React.Component {
  onSearch(event) {
    event.preventDefault();
    this.props.onSearch(event.target.value.trim());
  }
  render () { return (<input onChange={this.onSearch.bind(this)} />); }
}

测试失败是因为,正如您在事件对象上定义 preventDefault 函数一样,您还必须定义在 onSearch 函数上使用的其他属性。

 it('should call onChange prop', () => {
  const onSearchMock = jest.fn();
  const event = {
    preventDefault() {},
    target: { value: 'the-value' }
  };
  const component = enzyme.shallow(<InputBox onSearch={onSearchMock} />);
  component.find('input').simulate('change', event);
  expect(onSearchMock).toBeCalledWith('the-value');
});

之前的测试代码需要定义事件形状,因为您使用的是浅层渲染。如果您想测试您的 onSearch 函数是否使用了实际输入值,则需要尝试使用 enzyme.mount 进行完整渲染:

 it('should call onChange prop with input value', () => {
  const onSearchMock = jest.fn();
  const component = enzyme.mount(<InputBox onSearch={onSearchMock} value="custom value" />);
  component.find('input').simulate('change');
  expect(onSearchMock).toBeCalledWith('custom value');
});

原文由 Carloluis 发布,翻译遵循 CC BY-SA 4.0 许可协议

对于那些使用 TypeScript 的测试(并借鉴上面的答案),您需要执行类型强制转换 ( as React.ChangeEvent<HTMLInputElement> ) 以确保 linter 可以将签名视为兼容:

反应文件

export class InputBox extends React.Component<inputProps, searchState> {
  onSearch(event: React.ChangeEvent<HTMLInputElement>){
    event.preventDefault();
    //the actual onclick event is in another Component
    this.props.onSearch(event.target.value.trim());
  }

  render() {
    return (
      <input
        onChange={this.onSearch} //need to test this
        className={this.props.className}
        type="text"
        value={this.props.value}
        placeholder={this.props.placeholder} />
      );
  }
}

测试文件

it('should call onChange prop', () => {
  const onSearchMock = jest.fn();
  const event = {
    target: { value: 'the-value' }
  } as React.ChangeEvent<HTMLInputElement>;
  const component = enzyme.shallow(<InputBox onSearch={onSearchMock} />);
  component.find('input').simulate('change', event);
  expect(onSearchMock).toBeCalledWith('the-value');
});

或者

it('should call onChange prop', () => {
  const onSearchMock = jest.fn();
  const event = {
    target: { value: 'the-value' }
  } as React.ChangeEvent<HTMLInputElement>;
  const component = enzyme.mount<InputBox>(<InputBox onSearch={onSearchMock} />);
  const instance = component.instance();
  instance.onSearch(event);
  expect(onSearchMock).toBeCalledWith('the-value');
});

原文由 FrostyDog 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进