[英]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 暗示我正在对不可迭代的实例进行一些解构,并且日志显示了一些东西,无论我怎么想,它都会完美运行,但我不知道图像中显示的这段代码有什么问题以下:
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
覆盖整个模块,不适合您的用例,因为您只想模拟useField
和useFormikContext
。
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 的完整工作小示例。
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.