繁体   English   中英

Jest 快照测试 TypeError:尝试解构不可迭代实例无效

[英]Jest snapshot testing TypeError: Invalid attempt to destructure non-iterable instance

我的 React 代码库中有一个组件,我正在尝试为它创建一些快照测试,但不幸的是发生了一些奇怪的错误。 Jest 暗示我正在对不可迭代的实例进行一些解构,并且日志显示了一些东西,无论我怎么想,它都会完美运行,但我不知道图像中显示的这段代码有什么问题以下:

1

另请注意,我在我的组件中对formik进行了模拟,如下所示:

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

与该主题相关的所有其他问题要么不适合 Jest,要么答案不起作用甚至不被接受!

这是我的测试文件:

import React from 'react';
import renderer from 'react-test-renderer';

import MyComponent from '../MyComponent';

jest.mock('../MyComponentManager');
jest.mock('formik', () => ({
  useField: jest.fn(),
  useFormikContext: jest.fn().mockReturnValue({ isValidating: false, setFieldValue: () => {} }),
}));

describe('MyComponent', () => {
  test('should render component properly', () => {
    const component = renderer.create(<MyComponent />);
    const tree = component.toJSON();
    expect(tree).toMatchSnapshot();
  });
});

这是正在测试的组件的次要版本:


const MyComponent = () => {

  <SomeWrapperComponent>
    ...some jsx
    <NumberField {...props} />
  </SomeWrapperComponent>

}

并且错误发生在<NumberField />组件旁边。

我相信你的问题是设置useFormikContext: jest.fn() jest.fn()默认返回一个函数,该函数返回jest docs 中提到的undefined 然后你尝试解构undefined

您需要模拟useFormikContext函数的返回值:

jest.mock('formik', () => ({
  useField: jest.fn(),
  useFormikContext: jest.fn().mockReturnValue({ isValidating: false, setFieldValue: () => {} }),
}));

如果这没有帮助,请添加不起作用的完整简单的可运行示例,以便我可以更深入地了解。 (即测试文件和代码文件)


编辑

我看到您只嘲笑了formik模块的useField useFormikContext函数,尽管您可能更多地使用了formik模块中的formik ,例如Formik标记等,但它们现在已被覆盖。

jest.mock覆盖整个模块,不适合您的用例,因为您只想模拟useFielduseFormikContext

我喜欢使用jest.spyOn ,它可用于仅模拟模块的特定功能。 请参阅jest.spyOn上的笑话文档

这是在玩笑反应测试中模拟 formik 的完整工作小示例。

  1. example.js - 正在测试的反应组件。
  2. example.spec.js - 简单的玩笑测试

例子.js:

import React from 'react';
import { useFormikContext, Formik, Form, Field } from 'formik';

export const OtherComponent = () => {
  // Grab values and submitForm from context
  const { isValidating, setFieldValue } = useFormikContext();

  return (
    <div>
      <div>{isValidating ? 'validating...' : 'validated!'}</div>
      <button type="submit" disabled={isValidating}>
        submit
      </button>
      <button
        type="button"
        disabled={isValidating}
        onClick={() => {
          setFieldValue('token', '123456');
        }}
      >
        return to default
      </button>
    </div>
  );
};

export const ExmpleComponent = () => {
  return (
    <div>
      <h1>Example</h1>
      <Formik
        initialValues={{ token: '' }}
        validate={(values) => {
          return new Promise((resolve, _reject) => setTimeout(resolve, 3000)).then(() => {
            // wait 3 seconds
            const errors = {}; // no errors
            return errors;
          });
        }}
        onSubmit={(_values, _actions) => {
          console.log('submitted!');
        }}
      >
        <Form>
          <Field name="token" type="tel" />
          <OtherComponent />
        </Form>
      </Formik>
    </div>
  );
};

示例.spec.js:

import React from 'react';

import renderer from 'react-test-renderer';
import * as formik from 'formik';
import { ExmpleComponent } from '../src/example.js';

// jest.mock('formik', () => ({
//   useField: jest.fn(),
//   useFormikContext: jest.fn().mockReturnValue({ isValidating: false, setFieldValue: () => {} }),
// }));

describe('MyComponent', () => {
  test('should render component properly', () => {
    const useFieldSpy = jest.spyOn(formik, 'useField');
    const useFormikContextSpy = jest.spyOn(formik, 'useFormikContext');

    useFieldSpy.mockReturnValue(undefined);
    useFormikContextSpy.mockReturnValue({ isValidating: true, setFieldValue: () => {} });

    const component = renderer.create(<ExmpleComponent />);
    const tree = component.toJSON();
    expect(tree.children[1].children[1].children[0].children[0]).toBe('validating...');

    useFieldSpy.mockRestore();
    useFormikContextSpy.mockRestore();
  });
});

如果这仍然不起作用,请添加完整简单的示例,我可以自己运行以进行测试,以查看您的代码中有什么问题。 您添加了测试文件的完整示例,但未添加您正在测试的代码。

对于贡献,我使用以下代码解决了类似的问题:

jest.mock('formik', () => ({
  useField: jest.fn(),
  useFormikContext: jest.fn().mockReturnValue({ 
    setFieldValue: () => {}, 
    handleChange: () => {},
    initialValues: {} as AddDoctorInfoFormValues, 
    errors: {} as FormikErrors<AddDoctorInfoFormValues>,
    values: {} as AddDoctorInfoFormValues, 
  }),
}));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM