![](/img/trans.png)
[英]TypeError: Invalid attempt to destructure non-iterable instance React/Jest
[英]Jest snapshot testing TypeError: Invalid attempt to destructure non-iterable instance
我的 React 代码库中有一个组件,我正在尝试为它创建一些快照测试,但不幸的是发生了一些奇怪的错误。 Jest 暗示我正在对不可迭代的实例进行一些解构,并且日志显示了一些东西,无论我怎么想,它都会完美运行,但我不知道图像中显示的这段代码有什么问题以下:
另请注意,我在我的组件中对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
覆盖整个模块,不适合您的用例,因为您只想模拟useField
和useFormikContext
。
我喜欢使用jest.spyOn
,它可用于仅模拟模块的特定功能。 请参阅jest.spyOn
上的笑话文档。
这是在玩笑反应测试中模拟 formik 的完整工作小示例。
例子.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.