如何在用jest编写单元测试时模拟formik useFormikContext钩子

vhipe2zx  于 2023-02-27  发布在  Jest
关注(0)|答案(2)|浏览(197)

我有一个简单的组件,见下文,它基本上试图使用useFormikContext钩子从formik FormContext中获取一些数据。
然而,当试图为这个组件编写单元测试时,它希望我模拟钩子,这很好,然而,用类型脚本模拟钩子意味着返回20多个属性,其中大多数是各种方法和函数。
有没有人找到一个更好的方法来做到这一点?只是似乎有点烦人,即使我得到它的工作,因为我只需要1场从挂钩。

    • 组件**
const AphControlInput: React.FC<IAphControlInput> = ({ name, value, label, type, small, disabled, vertical = true, className = '', ...attributeOptions }) => {
  const form = useFormikContext();

  return (
    <>
      <div className={
        `aph-control-input ${className}` +
        `${small ? ' aph-control-input--small' : ''}` +
        `${vertical ? ' aph-control-input--block' : ''}` +
        `${form.getFieldMeta(name).error ? ' aph-control-input--invalid' : ''}`
      }
      >
        <Field
          className='aph-control-input__input'
          name={name}
          id={value ? value?.toString() : name}
          type={type}
          value={value ? value : undefined}
          disabled={disabled}
          {...attributeOptions}
        />
        <label className='aph-control-input__text' htmlFor={value ? value?.toString() : name}>
          {label}
        </label>
      </div>
    </>
  );
};
    • 单元测试**(不完整,这只是模拟钩子的所有返回值的快速尝试)
describe('AphInputLabel UnitTests', () => {
  let wrapper: any;
  const useFormikContextMock = jest.spyOn(formik, 'useFormikContext');

  beforeEach(() => {
    useFormikContextMock.mockReturnValue({
      values: { testName: 'testValue' },
      getFieldMeta: getFieldMetaMock,
      touched: true,
      isSubmitting: false,
      isValidating: false,
      errors: false,
      submitCount: 0,
      setStatus: (status?: any) => { return null },
      setErrors: (errors?: FormikErrors<any>) => { return null },
      setSubmitting: (isSubmitting: boolean) => { return null },
      setTouched: (touched: FormikTouched<any>, shouldValidate?: boolean) => { return null },
      setValues: (values: React.SetStateAction<any>, shouldValidate?: boolean) => { return null },
      setFieldValue: (field: string, value: any, shouldValidate?: boolean) => { return null },
      setFieldError: (field: string, message: string | undefined) => { return null },
      setFieldTouched: (field: string, isTouched?: boolean, shouldValidate?: boolean) => { return null },
      resetForm: (nextState?: Partial<FormikState<any>>) => { return null },
      validateField: (field: string) => { return null },
      setFormikState: (f: FormikState<any> | ((prevState: FormikState<any>) => FormikState<any>), cb?: () => void) => null,
      validateForm: (values?: any) => { return new Promise<FormikErrors<unknown>>((resolve, reject) => {
        const formikErrors: FormikErrors<any> = {
          'testName': ''
        }
          return formikErrors;
        });
      },
      submitForm: () => new Promise<void>(() => null),
      handleSubmit: (e?: React.FormEvent<HTMLFormElement> | undefined) => null,
      handleReset: (e?: React.SyntheticEvent<any>) => null,
    });
  }
}
qoefvg9y

qoefvg9y1#

我解决了这个问题,不是100%肯定这是最好的解决方案,但已张贴在这里的情况下,它有助于任何人与类似的问题。
我基本上覆盖了FormikType,允许我忽略所有我没有使用的字段和方法,它显然有一些缺点,因为它删除了类型安全,但我认为,因为它只在单元测试中,这是可以的。

导入

import * as Formik from 'formik';

测试设置

describe('AphControlInput: UnitTests', () => {
  let wrapper: any;
  const useFormikContextMock = jest.spyOn(Formik, 'useFormikContext');

  beforeEach(() => {
    useFormikContextMock.mockReturnValue({
      getFieldMeta: getFieldMetaMock
    } as unknown as any);

    wrapper = shallow(
      <AphTextInput {...baseComponentProps} />
    );
  });
}

帮助器方法

export const getFieldMetaMock = (name: string) => {
  return ({
    value: 'testValue',
    initialTouched: true,
    touched: false,
  });
};
ztmd8pv5

ztmd8pv52#

同样,你可以模仿Formik库和它想要的函数,用这种方式:

jest.mock('formik', () => ({
  useFormikContext: jest.fn().mockReturnValue({
    getFieldMeta: jest.fn(),
  }),
}));

只需将此代码放在单元测试文件的顶部,在describe范围之外。

相关问题