Reactjs 在React/Jest单元测试中,如何模拟被模拟组件调用的事件属性?

Reactjs 在React/Jest单元测试中,如何模拟被模拟组件调用的事件属性?,reactjs,mocking,jestjs,Reactjs,Mocking,Jestjs,假设我有一个React组件,它是一个带有用户名字段的登录表单。如果用户将用户名设置为空字符串,组件将显示错误消息 代码如下: const LoginForm = () => { const [errorMessage, setErrorMessage] = useState(''), handleOnChangeUsername = (newUsername: string) => { if (newUsername.trim() === '') {

假设我有一个React组件,它是一个带有用户名字段的登录表单。如果用户将用户名设置为空字符串,组件将显示错误消息

代码如下:

const LoginForm = () => {
  const [errorMessage, setErrorMessage] = useState(''),
    handleOnChangeUsername = (newUsername: string) => {
      if (newUsername.trim() === '') {
        setErrorMessage('Username is required.');
      } else {
        setErrorMessage('');
      }
    };

  return (
    <form>
      <UsernameField onChange={handleOnChangeUsername} />
      {errorMessage && <Error message={errorMessage} />}
    </form>
  );
};
const LoginForm=()=>{
常量[errorMessage,setErrorMessage]=使用状态(“”),
handleOnChangeUsername=(新用户名:字符串)=>{
如果(newUsername.trim()=''){
setErrorMessage('需要用户名');
}否则{
setErrorMessage(“”);
}
};
返回(
{errorMessage&&}
);
};
我想对这个组件进行单元测试

因此,我想编写一个测试,验证当用户输入一个空白用户名时,下面会显示错误消息:“username is required”

为了编写此单元测试,我假设需要执行以下操作:

  • 装载LoginForm组件,提供模拟的UsernameField组件

  • 让模拟的UsernameField组件调用其onChange属性,传入一个空字符串

  • 断言LoginForm组件现在正在呈现一个错误组件(即handleOnChangeUsername中的代码实际运行并产生了正确的副作用)

  • 模拟部分很简单——我只调用jest.mock(…),将路径传递给模块和模拟实现

    棘手的一点是步骤2。我如何使我的单元测试使mock调用它自己的一个道具,以模拟使用空字符串调用onChange

    似乎必须有某种渠道,单元测试代码可以通过这种渠道与模拟组件的内部道具进行通信

    在React/Jest单元测试中有没有一种简单和/或惯用的方法来实现这一点


    注:此问题假设为一个问题。我知道有些开发人员可能会说,我应该通过操纵Username组件呈现的DOM元素直接触发Username onChange。我已经知道怎么做了。但是我想遵循模仿者的风格,完全模仿用户名组件。

    好的,我似乎至少找到了一种访问道具的方法。但这需要;仍然不知道如何在没有酶的情况下做到这一点

    Ezyme的包装器包括一个方法,该方法返回包装组件的道具

    所以我可以这样写:

    const root = mount(<LoginForm />);
    root.find("UsernameField").props().onChange("");
    expect(root.find("Error").exists()).toBeTruthy();
    
    const root=mount();
    root.find(“UsernameField”).props().onChange(“”);
    expect(root.find(“Error”).exists()).toBeTruthy();
    
    Jest有一个模拟整个模块的系统。你应该开始了。基本上,您的模拟组件需要包装在
    React.forwardRef()
    中,并且应该实现一个
    useImperialiveHandle()
    钩子,该钩子公开您可以在测试中调用的API;在本例中,一些函数使用您在测试中提供的值调用
    onChange
    prop。