简体   繁体   English

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

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

I have a component in my React codebase and I am trying to create some snapshot tests for it, but unfortunately there is some weird error going on.我的 React 代码库中有一个组件,我正在尝试为它创建一些快照测试,但不幸的是发生了一些奇怪的错误。 Jest implies that I'm doing some destructuring on non-iterable instance and logs shows something that however much I tried to think about it, it would work perfectly, but I don't know what is wrong with this snippet of code shown in image below: Jest 暗示我正在对不可迭代的实例进行一些解构,并且日志显示了一些东西,无论我怎么想,它都会完美运行,但我不知道图像中显示的这段代码有什么问题以下:

1

Also please note that I did a mock for formik in my component like below:另请注意,我在我的组件中对formik进行了模拟,如下所示:

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

and every other question related to the topic either is not for Jest or answer is not working and not even accepted!与该主题相关的所有其他问题要么不适合 Jest,要么答案不起作用甚至不被接受!

Here is my test file:这是我的测试文件:

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();
  });
});

And here is the minor version of the component that is being testing:这是正在测试的组件的次要版本:


const MyComponent = () => {

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

}

and the error happens in side the <NumberField /> component.并且错误发生在<NumberField />组件旁边。

I believe your problem is setting useFormikContext: jest.fn() .我相信你的问题是设置useFormikContext: jest.fn() jest.fn() by default returns a function that returns undefined as mentioned in jest docs . jest.fn()默认返回一个函数,该函数返回jest docs 中提到的undefined and by that you try to deconstruct undefined .然后你尝试解构undefined

you need to mock the return value of useFormikContext function:您需要模拟useFormikContext函数的返回值:

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

If that doesnt help, please add full and simple runnable example that's not working, so I can take a deeper look.如果这没有帮助,请添加不起作用的完整简单的可运行示例,以便我可以更深入地了解。 (ie test file and code file) (即测试文件和代码文件)


Edit编辑

I see you only mocked useField useFormikContext functions of formik module, although you probably use more from formik module, like Formik tag and such, but they're now overriden.我看到您只嘲笑了formik模块的useField useFormikContext函数,尽管您可能更多地使用了formik模块中的formik ,例如Formik标记等,但它们现在已被覆盖。

jest.mock overrides the whole module, and not suitable for your use case, because you only want to mock only useField & useFormikContext . jest.mock覆盖整个模块,不适合您的用例,因为您只想模拟useFielduseFormikContext

I like to use jest.spyOn which can be used to mock only specific functions of a module.我喜欢使用jest.spyOn ,它可用于仅模拟模块的特定功能。 see jest docs on jest.spyOn .请参阅jest.spyOn上的笑话文档

Here's full working small example mocking formik in jest react testing.这是在玩笑反应测试中模拟 formik 的完整工作小示例。

  1. example.js - react component that's being tested. example.js - 正在测试的反应组件。
  2. example.spec.js - simple jest test example.spec.js - 简单的玩笑测试

example.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>
  );
};

example.spec.js:示例.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();
  });
});

If that still doesnt work, please add full & simple example that I can run to test by myself to see what's wrong in your code.如果这仍然不起作用,请添加完整简单的示例,我可以自己运行以进行测试,以查看您的代码中有什么问题。 You added full example of the test file, but not the code you're testing.您添加了测试文件的完整示例,但未添加您正在测试的代码。

For contribute, I solved similar issue using this code:对于贡献,我使用以下代码解决了类似的问题:

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.

相关问题 TypeError:对不可迭代实例 React/Jest 的解构尝试无效 - TypeError: Invalid attempt to destructure non-iterable instance React/Jest 未处理的拒绝(TypeError):破坏非迭代实例的无效尝试 - Unhandled Rejection (TypeError): Invalid attempt to destructure non-iterable instance 未捕获的 TypeError:无效的解构不可迭代实例的尝试 - Uncaught TypeError: Invalid attempt to destructure non-iterable instance 解构不可迭代实例的无效尝试 - Invalid attempt to destructure non-iterable instance React,获取 TypeError:在将全局状态与 Context 结合使用时,尝试解构不可迭代的实例无效 - React, Getting TypeError: Invalid attempt to destructure non-iterable instance when using global state with Context 使用反应测试库时尝试解构不可迭代实例无效 - Invalid attempt to destructure non-iterable instance while using react testing library TypeError:无效的解构不可迭代实例的尝试。 为了可迭代,非数组对象必须有一个 [Symbol.iterator]() - TypeError: Invalid attempt to destructure non-iterable instance. In order to be iterable, non-array objects must have a [Symbol.iterator]() 未处理的拒绝(TypeError):散布不可迭代实例的无效尝试 - Unhandled Rejection (TypeError): Invalid attempt to spread non-iterable instance React Uncaught TypeError:传播不可迭代实例的无效尝试 - React Uncaught TypeError: Invalid attempt to spread non-iterable instance 类型错误:传播不可迭代实例和合成事件的尝试无效 - TypeError: Invalid attempt to spread non-iterable instance and Synthetic Events
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM