使用Jest和Enzyme测试FaC时找不到React Node节点
我正在React Native中构建一个应用程序.我们最近开始在应用程序中使用TypeScript,我的任务是迁移单元测试.有一项测试奇迹般地失败了.
I'm building an app in React Native. We recently started using TypeScript in the app and my task is to migrate the unit tests. There is one test that is miracously failing.
该应用程序的<LoginForm />
使用 Formik .
//... imports
export interface FormValues {
email: string;
password: string;
}
export interface Props {
navigation: NavigationScreenProp<any, any>;
}
export default class LoginForm extends Component<Props, object> {
handleSubmit = (values: FormValues, formikBag: FormikActions<FormValues>) => {
// ... api calls and stuff
};
renderForm = ({
values,
handleSubmit,
setFieldValue,
touched,
errors,
setFieldTouched,
isValid,
isSubmitting
}: FormikProps<FormValues>) => (
<View style={styles.container}>
// ... two inputs and a button
</View>
);
render() {
return (
<Formik
initialValues={{ email: "", password: "" }}
onSubmit={(values: FormValues, formikBag: FormikActions<FormValues>) =>
this.handleSubmit(values, formikBag)
}
validationSchema={<some_schema>}
render={(formikBag: FormikProps<FormValues>) => this.renderForm(formikBag)}
/>
);
}
}
这是单元测试查找子功能" renderForm()
的方式:
This is how the unit test looks for the Function as Child renderForm()
:
describe("renderForm", () => {
let formWrapper: ShallowWrapper;
beforeEach(() => {
let formikBagMock: any = {
values: { email: "Test Email", password: "testpassword" },
handleSubmit: jest.fn(),
setFieldValue: jest.fn(),
errors: { email: "Test error", password: "" },
touched: { email: true, password: false },
setFieldTouched: jest.fn(),
isValid: false,
isSubmitting: false
};
formWrapper = shallow(wrapper.instance().renderForm(formikBagMock));
});
it("should render a <View />", () => {
expect(formWrapper.find("View")).toHaveLength(1);
});
it("should render two <Input />", () => {
expect(formWrapper.find("Input")).toHaveLength(2);
});
it("should render a <Button />", () => {
expect(formWrapper.find("Button")).toHaveLength(1);
});
describe("styling", () => {
it("should give the <View /> the 'container' style", () => {
expect(formWrapper.find(View).prop("style")).toEqual(styles.container);
});
});
});
问题在于,虽然此测试在.js
中通过,但在.tsx
中却失败.
The problem is that, while this test was passing in .js
it is failing in .tsx
.
The error thrown looks like this:
● LoginForm › rendering › renderForm › should render a <Button />
expect(received).toHaveLength(length)
Expected value to have length:
1
Received:
{Symbol(enzyme.__root__): {Symbol(enzyme.__root__): [Circular], Symbol(enzyme.__unrendered__): <Component style={{"alignItems": "center", "flex": 1, "justifyContent": "space-evenly"}}><Input autoCapitalize="none" editable={true} errorMessage="Test error" keyboardType="email-address" onBlur={[Function onBlur]} onChangeText={[Function onChangeText]} placeholder="Email address" value="Test Email" /><Input autoCapitalize="none" editable={true} onBlur={[Function onBlur]} onChangeText={[Function onChangeText]} placeholder="Password" secureTextEntry={true} value="testpassword" /><Button TouchableComponent={[Function anonymous]} buttonStyle={{"backgroundColor": "#DC4F19"}} clear={false} containerStyle={{"paddingVertical": 5, "width": "33%"}} disabled={true} disabledStyle={{"backgroundColor": "#DC4F19", "opacity": 0.3}} disabledTitleStyle={{"color": "white"}} iconRight={false} loading={false} loadingProps={{"color": "white", "size": "large"}} onPress={[Function mockConstructor]} raised={false} title="Log In" titleStyle={{"color": "white"}} /></Component>, Symbol(enzyme.__renderer__): {"batchedUpdates": [Function batchedUpdates], "getNode": [Function getNode], "render": [Function render], "simulateError": [Function simulateError], "simulateEvent": [Function simulateEvent], "unmount": [Function unmount]}, Symbol(enzyme.__node__): {"instance": null, "key": undefined, "nodeType": "function", "props": {"children": [Function anonymous]}, "ref": null, "rendered": [Function anonymous], "type": {"$$typeof": Symbol(react.context), "Consumer": [Circular], "Provider": {"$$typeof": Symbol(react.provider), "_context": [Circular]}, "_calculateChangedBits": null, "_currentRenderer": null, "_currentRenderer2": null, "_currentValue": false, "_currentValue2": false, "unstable_read": [Function bound readContext]}}, Symbol(enzyme.__nodes__): [{"instance": null, "key": undefined, "nodeType": "function", "props": {"children": [Function anonymous]}, "ref": null, "rendered": [Function anonymous], "type": {"$$typeof": Symbol(react.context), "Consumer": [Circular], "Provider": {"$$typeof": Symbol(react.provider), "_context": [Circular]}, "_calculateChangedBits": null, "_currentRenderer": null, "_currentRenderer2": null, "_currentValue": false, "_currentValue2": false, "unstable_read": [Function bound readContext]}}], Symbol(enzyme.__options__): {"adapter": {"options": {"enableComponentDidUpdateOnSetState": true, "lifecycles": {"componentDidUpdate": {"onSetState": true}, "getDerivedStateFromProps": true, "getSnapshotBeforeUpdate": true, "setState": {"skipsComponentDidUpdateOnNullish": true}}}}, "attachTo": undefined, "hydrateIn": undefined}}, Symbol(enzyme.__unrendered__): null, Symbol(enzyme.__renderer__): {"batchedUpdates": [Function batchedUpdates], "getNode": [Function getNode], "render": [Function render], "simulateError": [Function simulateError], "simulateEvent": [Function simulateEvent], "unmount": [Function unmount]}, Symbol(enzyme.__node__): undefined, Symbol(enzyme.__nodes__): [], Symbol(enzyme.__options__): {"adapter": {"options": {"enableComponentDidUpdateOnSetState": true, "lifecycles": {"componentDidUpdate": {"onSetState": true}, "getDerivedStateFromProps": true, "getSnapshotBeforeUpdate": true, "setState": {"skipsComponentDidUpdateOnNullish": true}}}}, "attachTo": undefined, "hydrateIn": undefined}}
received.length:
0
61 |
62 | it("should render a <Button />", () => {
> 63 | expect(formWrapper.find("Button")).toHaveLength(1);
| ^
64 | });
65 |
66 | describe("styling", () => {
怎么可能是,酶突然找不到了该节点?我什至尝试直接导入组件View
,Button
和Input
并将其传递给find()
而不是字符串,但这并没有改变.我在做什么错了?
How can it be, that Enzyme suddenly does not find the node anymore? I even tried importing the components View
, Button
and Input
directly and passing that to find()
instead of the strings, but it doesn't change anything. What am I doing wrong?
您可以比较.js
和.tsx
文件中的formWrapper.debug()
,以查看有什么不同.
You can compare formWrapper.debug()
in the .js
and .tsx
files to see what's different.
由于您使用的是 Shallow Rendering
,因此您可能需要到 dive()
来点击Button
.使用console.log(formWrapper.debug())
查看呈现的内容.
Since you're using Shallow Rendering
you might need to dive()
to hit Button
. Use console.log(formWrapper.debug())
to see what is rendered.
如果仅渲染View
,请尝试:expect(formWrapper.dive().find("Button")).toHaveLength(1)
If only View
is rendered, try: expect(formWrapper.dive().find("Button")).toHaveLength(1)