开玩笑的酶模拟功能无法与toHaveBeenCalled和嘲笑.calls.length

时间:2020-09-14 05:00:21

标签: reactjs unit-testing jestjs enzyme

我正在学习反应单元测试,我编写了简单的测试用例,但没有用,我在很多地方用google搜索过,看到相同的示例,那对我不起作用。我尝试了两种方法都具有HaveBeenCalled / mock.calls.length。

计数器正在增加,我知道我可以检查/测试计数器值以了解是否单击了按钮,但是如果没有计数器,我只想确保按钮单击会触发功能呢?

我知道是否将此功能移至其他文件然后导入,然后在测试下进行,因为我将该功能作为道具传递了。但是,如果我想测试未导入且在同一文件中的函数,该怎么办?

Sandbox Demo

import React from "react";
import "./Login.css";

class Login extends React.Component {
  state = {
    counter: 0
  };

  doLogin = (event) => {
    let { counter } = this.state;
    this.setState((prevstate) => ({ counter: prevstate.counter + 1 }));
    // console.log("Handle login button click");
  };

  render() {
    const { counter } = this.state;
    return (
      <table width="100%" border="0" cellPadding={4}>
        <tr>
          <td>
            <input type="text" name="username" placeholder="Username" />
          </td>
        </tr>
        <tr>
          <td>
            <input type="password" name="password" placeholder="Password" />
          </td>
        </tr>
        <tr>
          <td>
            <button onClick={this.doLogin}>LogIn</button>
            &nbsp;&nbsp;{counter}
          </td>
        </tr>
      </table>
    );
  }
}

export default Login;

测试用例

it("Handle login button click", () => {
  const mockOnClick = jest.fn();

  const wrapper = shallow(<Login onClick={mockOnClick} />);
  wrapper.find("button").simulate("click");
  wrapper.find("button").simulate("click");
  // mockOnClick();
  console.log(wrapper.state("counter"));
  // expect(mockOnClick).toHaveBeenCalled();
  expect(mockOnClick.mock.calls.length).toEqual(2);
});

1 个答案:

答案 0 :(得分:0)

由于onClick事件位于button而非Login组件上,因此该函数未按您期望的方式绑定。您实际上要做的是模拟组件,然后用伪造的函数替换

it("Handle login button click", () => {
  const mockOnClick = jest.fn();

  const wrapper = shallow( < Login / > );
  wrapper.instance().doLogin = mockOnClick;
  //MUST forceUpdate or the first .simulate call will trigger the real function.
  wrapper.instance().forceUpdate();  
  wrapper.find("button").simulate("click");
  wrapper.find("button").simulate("click");
  // mockOnClick();
  console.log(wrapper.state("counter"));
  // expect(mockOnClick).toHaveBeenCalled();
  expect(mockOnClick.mock.calls.length).toEqual(2);
});

https://codesandbox.io/s/amazing-easley-hd0hc

请注意,instance必须为forceUpdate,以避免调用实函数。另外,这是用伪函数代替了实际函数,而不是调用真实函数,因此仅测试了onClick机制本身,而这实际上并不是对应用程序功能的有用测试。