简体   繁体   English

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

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

I'm testing a component method called handleSubmit (the name doesn't matter...). 我正在测试一个名为handleSubmit的组件方法(名称无关紧要......)。

Test 测试

// ...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();
});

Component 零件

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;

I keep getting this error message, which is annoying now: 我一直收到此错误消息,现在很烦人:

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

Expected mock function to have been called.

But if I create a fake component inside the test then it works 但是,如果我在测试中创建了一个假组件,那么它就可以了

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

Is it something to do with shallow() or mount from enzyme with imported components? 是否与shallow()或使用进口组件的enzyme mount I've spent many days looking for answers but I'm lost. 我花了很多天寻找答案,但我迷路了。

Adding to @rauliyohmc answer. 添加到@rauliyohmc答案。 The problem is that even after mocking the component method it is not getting called and instead, the actual method is called. 问题是,即使在模拟组件方法之后,它也不会被调用,而是调用实际方法。 So, after spending some time on it, I found out a solution. 所以,花了一些时间,我发现了一个解决方案。 You'll need to forceUpdate your component after mocking its method. 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();
}); 

Minimal example: gist 最小的例子: 要点

The problem is that you are not mocking the component method itself, but rather creating a new mock function and assign it to a random variable. 问题是你没有嘲笑组件方法本身,而是创建一个新的模拟函数并将其分配给一个随机变量。

Try to mock the method through the object prototype before rendering as follows: 尝试在呈现之前通过对象原型模拟方法,如下所示:

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

Note : not sure which jest version are you using but since Jest v15, automocking is disabled by default, so you need to explicitly mock your module before importing it in the file. 注意 :不确定您使用的是哪个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