繁体   English   中英

Jest.fn()在React单元测试中不起作用

[英]Jest.fn() not working in React unit-test

我正在测试一个名为handleSubmit的组件方法(名称无关紧要......)。

测试

// ...imported all modules at the top, including enzyme

it('should submit form data', () => {
  let form = shallow(<Form />);
  let handleSubmit = jest.fn(); // <= this doesn't work!!

  form.find('.submit-btn').simulate('click');

  expect(form.find('.submit-btn').length).toEqual(1);
  expect(handleSubmit).toHaveBeenCalled();
});

零件

import React, { Component } from 'react';
import axios from 'axios';

class CarnetSidebarForm extends Component {
  constructor(props) {
    super(props);

    this.state = {
      title: ''
    };

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(e) {
    const target = e.target;
    const value = target.value;
    const name = target.name;

    this.setState({
      [name]: value
    });
  }

  handleSubmit(e) {
    e.preventDefault();

    let payload = {
      title: this.state.title
    };

    this.postCard(payload);

    console.log('Payload: ', payload);
  }

  postCard(data) {
    return axios.post('http://localhost:4000/api/cards', data)
      .then(response => {
        console.log('Response: ', response.message);
      });
  }

  render() {
    return (
      <div className="card-form-panel">
        <form className="card-form" onSubmit={this.handleSubmit}>
          <div className="form-group">
            <label htmlFor="card-title-field">Title</label>
            <input className="form-control"
               type="text"
               placeholder="Title..."
               id="card-title-field"
               name="title"
               value={this.state.title}
               onChange={this.handleChange} />
          </div>

          <input className="card-submit-btn btn btn-primary" type="submit" value="Save" />
        </form>
      </div>
    );
  }
}

export default CarnetSidebarForm;

我一直收到此错误消息,现在很烦人:

expect(jest.fn()).toHaveBeenCalled()

Expected mock function to have been called.

但是,如果我在测试中创建了一个假组件,那么它就可以了

it('should submit form data', () => {
  let handleSubmit = jest.fn();

  // create a fake component
  let form = mount(
    <form onSubmit={handleSubmit}>
      <input className="submit-btn" type="submit" value="Save" />
    </form>
  );

  form.find('.submit-btn').simulate('submit');

  expect(form.find('.submit-btn').length).toEqual(1);
  expect(handleSubmit).toHaveBeenCalled();
});

是否与shallow()或使用进口组件的enzyme mount 我花了很多天寻找答案,但我迷路了。

添加到@rauliyohmc答案。 问题是,即使在模拟组件方法之后,它也不会被调用,而是调用实际方法。 所以,花了一些时间,我发现了一个解决方案。 forceUpdate其方法后,您需要forceUpdate组件。

it('should submit form data', () => {
  let form = mount(<Form />); // need to use mount to make it work.
  form.instance().handleSubmit = jest.fn();
  form.update(); // equivalent to calling form.instance().forceUpdate();

  form.find('.submit-btn').simulate('submit'); // simulated event must be submit

  expect(form.find('.submit-btn').length).toEqual(1);
  expect(form.instance().handleSubmit).toHaveBeenCalled();
}); 

最小的例子: 要点

问题是你没有嘲笑组件方法本身,而是创建一个新的模拟函数并将其分配给一个随机变量。

尝试在呈现之前通过对象原型模拟方法,如下所示:

jest.mock('../Form'); // mock the component before importing it using the right path
import Form from '../Form';
...
it('should submit form data', () => {
  Form.prototype.handleSubmit = jest.fn();
  let form = shallow(<Form />);

  form.find('.submit-btn').simulate('submit');

  expect(form.find('.submit-btn').length).toEqual(1);
  expect(Form.prototype.handleSubmit).toHaveBeenCalled();
}); 

注意 :不确定您使用的是哪个jest版本,但自Jest v15以来,默认情况下禁用自动插锁,因此您需要在将模块导入文件之前显式模拟该模块。

<input className="card-submit-btn btn btn-primary" type="submit" value="Save" />

你的组件没有使用className .submit-btn ,它使用的是.card-submit-btn

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM