如何模拟一个函数并期望它被调用?

IT技术 node.js reactjs jestjs react-testing-library
2021-05-17 01:57:39

我是 react-testing-library 的新手,长期以来一直在尝试测试一个功能。例如,我想检查当单击按钮时是否调用了给定的函数并抛出错误。所以任何帮助都将受到高度赞赏,如果可能,请与我分享任何有用的资源。

登录.js

export default class SignIn extends Component {
    constructor(props) {
        super(props);
        this.state = {
        };
    }

    handleClose = (event, reason) => { };
    validate = () => { };
    change = (e) => { };
    onSubmit = (e) => { };

    render() {
        return (<div>...</div>);
    }
}

完整:https : //github.com/blaise82/react-testing-library-try/blob/master/src/views/SignIn.js

这是我的测试

it('should submit form', async () => {
    const { getByLabelText, getByText, container, debug } = render(<SignIn />);
    const change = jest.fn();
    const onSubmit = jest.fn();
    const email = getByLabelText('email');
    const password = getByLabelText('password');
    const submit = getByLabelText('submit');

    userEvent.type(email, 'octopusbn@gmail.com');
    expect(email.value).toBe('octopusbn@gmail.com');
    expect(password.value).toBe('');
    expect(change).toHaveBeenCalled();

    console.log(password)
    await userEvent.click(submit);
    expect(onSubmit).toHaveBeenCalled();

});

完整:https : //github.com/blaise82/react-testing-library-try/blob/master/src/test/signin.test.js

结果

>    Expected number of calls: >= 1
>     Received number of calls:    0

请让我知道我做错了什么。

GitHub 上的完整代码:https : //github.com/blaise82/react-testing-library-try

2个回答

您可以通过模拟来自组件外部(又名依赖项)的所有内容来测试函数,例如 - prop 回调、外部库 api 等。

在开始之前,让我们先了解一下组件中的所有功能。通过组件,我可以将它们列出如下:

  1. 元素上的事件处理程序[如组件中的handleClose, onSubmit, change]
  2. 组件内部的函数,不与组件外部的状态/函数交互 [ validate]
  3. 被调用的props函数/库 apis [ axios.post]

让我们一一讨论——

  • 事件处理程序 &
  • 组件内部的函数不与组件外部的状态/函数交互

==> 附加到元素的事件处理程序可以安全地被调用。如果它们被调用,你不需要测试它们。相反,您应该测试的是它们被调用的后遗症。还有像这样的功能validate

让我们以change您要测试函数为例这个函数在被调用后设置状态,状态被反映到表单元素中。我们可以使用这样的助手断言表单元素的值

  • 被调用的props函数/库 apis [ axios.post]

==> 这些函数可以被模拟和测试它们被调用的调用/参数的数量。 https://jestjs.io/docs/en/mock-functions.html#mocking-modules

除了上面链接中给出的嘲笑笑话片段之外,在您的情况下 -

axios.post.toHaveBeenCalledWith(expectedParms);

您也可以让它返回您想要的结果/错误并测试相应的组件行为。

希望你觉得这有帮助。干杯!

我认为这是因为您实际上并没有将模拟函数传递给组件。您只是实例化了两个常量,它们碰巧具有您要查看的函数的名称,但实际上并未在组件中的任何地方使用。

听起来您想监视组件的内部函数以查看它们是否已被调用。

这是一个基于帖子(链接如下)的示例(未测试),可能对您有所帮助。

describe('spying on "onSubmit" method', () => {
  it('should call onSubmit when the button is clicked', () => {
    const wrapper = shallow(<SignIn />); 
    const instance = wrapper.instance();

    jest.spyOn(instance, 'onSubmit');

    wrapper.find('button').simulate('click');
    expect(instance.onSubmit).toHaveBeenCalled();
  });
});

帖子:https : //bambielli.com/til/2018-03-04-directly-test-react-component-methods/#spying-on-incrementcounter