在将状态从父组件传递到子组件时,我正在尝试这些状态方法
const [bio, setBio] = useState("");
const [gravatar, setGravatar] = useState("");
但我收到此错误
✓应检查EditProfile是否呈现子组件(2毫秒) ✕应该测试生物状态(4毫秒)
●应该渲染›应该测试生物状态
TypeError: Cannot read property 'target' of undefined
调用此测试时,我做错了什么?谢谢。
it("should test bio state", () => {
wrapper
.find("EditProfileForm")
.props()
.handleBio();
expect(setState).toHaveBeenCalledWith("set bio");
});
editProfile.test.tsx
import React from "react";
import EditProfile from "./editProfile";
import { shallow, mount, render } from "enzyme";
import EditProfileForm from "../forms/editProfile/editForm";
import { createShallow } from "@material-ui/core/test-utils";
import { Provider } from "react-redux";
import { store } from "../../store";
describe("Should render <EditProfile/>", () => {
let wrapper;
const setState = jest.fn();
const useStateSpy = jest.spyOn(React, "useState");
useStateSpy.mockImplementation((init) => [init, setState]);
beforeAll(() => {
wrapper = mount(
<Provider store={store}>
<EditProfile />
</Provider>,
);
});
it("Should render <EditProfile/>", () => {
expect(wrapper).toHaveLength(1);
});
it("Should check if EditProfile renders child component", () => {
expect(wrapper.find("EditProfileForm")).toHaveLength(1);
});
it("should test bio state", () => {
wrapper
.find("EditProfileForm")
.props()
.handleBio();
expect(setState).toHaveBeenCalledWith("set bio");
});
});
editProfile.tsx
import React, { useEffect, Component, useRef, useState } from "react";
import Typography from "@material-ui/core/Typography";
import EditProfileForm from "../forms/editProfile/editForm";
import GridHoc from "../hoc/grid";
import { Grid } from "@material-ui/core";
import storeMethods from "../../common/storeHooks";
function EditProfile(props: any) {
const [bio, setBio] = useState("");
const [gravatar, setGravatar] = useState("");
const mounted = useRef<Object>();
const { getProfile, profileData, userErr, message, updateProfile } = storeMethods();
useEffect(() => {
if (!mounted.current) {
getProfile();
mounted.current = true;
} else {
setBio(bio ? bio : profileData.bio);
setGravatar(gravatar ? gravatar : profileData.gravatar);
}
});
const handleSubmit = (e: any) => {
e.preventDefault();
const formData = {
bio,
gravatar,
};
updateProfile(formData);
};
return (
<Grid container={true} justify="center">
<Grid item={true} xs={12} sm={12} md={8} lg={8}>
{userErr && <Typography style={{ color: "red" }}>{message || userErr}</Typography>}
{message && <Typography style={{ color: "green" }}>{message || userErr}</Typography>}
<EditProfileForm handleBio={(e) => setBio(e.target.value)} handleGravatar={(e) => setGravatar(e.target.value)} onSubmit={handleSubmit} bio={bio} gravatar={gravatar} />
</Grid>
</Grid>
);
}
export default GridHoc(EditProfile);
editProfileForm
import Button from "@material-ui/core/Button";
import FormGroup from "@material-ui/core/FormGroup";
import FormLabel from "@material-ui/core/FormLabel";
import TextField from "@material-ui/core/TextField";
import Typography from "@material-ui/core/Typography";
import React from "react";
const EditProfileForm = (props: any) => (
<form onSubmit={props.onSubmit}>
<Typography variant="h5">Edit Profile</Typography>
<FormGroup style={{ padding: "30px 0px" }}>
<FormLabel style={{ display: "block" }}>Bio</FormLabel>
<TextField
id="outlined-name"
style={{
width: "100%",
}}
name="bio"
multiline={true}
rows="3"
defaultValue={props.bio}
onChange={props.handleBio}
margin="normal"
variant="outlined"
/>
<FormLabel style={{ display: "block" }}>Gravatar</FormLabel>
<TextField
id="outlined-name"
style={{
width: "100%",
}}
name="gravatar"
multiline={true}
rows="3"
onChange={props.handleGravatar}
defaultValue={props.gravatar}
margin="normal"
variant="outlined"
/>
</FormGroup>
<Button className="subBtn" variant="outlined" color="primary" type="submit">
Submit
</Button>
</form>
);
export default EditProfileForm;
答案 0 :(得分:1)
测试您调用handleBio
的方式有问题。测试应该模拟用户交互,但是这里您以编程方式调用handleBio
,这根本没用。
相反,您应该想象用户可以使用您的组件做什么,然后必须执行哪些操作。
在这里,您似乎测试了setBio
被调用时handleBio
是否被正确调用,这只是测试React正确绑定了道具(并且您不需要/不应该这样做)。
相反,您需要测试handleBio
的更改已调用TextField
,并且应该在EditProfileForm
测试中进行。
为此,您需要在TextField
上触发一个更改事件(如果用户更改了TextField
值,将会发生这种情况),只有在此之后,才期望handleBio
已使用正确的参数调用。
我建议您使用@testing-library/react,这将使您的测试更容易编写。
您可以在两个label
上都添加一个TextField
属性:
<TextField name="bio" label="bio" />
<TextField name="gravatar" label="gravatar" />
,然后编写以下测试:
// existing imports
import { render as testRender, fireEvent, screen } from '@testing-library/react';
const props = {
onSubmit: jest.fn(),
handleBio: jest.fn(),
handleGravatar: jest.fn(),
}
const render = () => testRender(<EditProfileForm {...props} />;
describe('EditProfile', () => {
...
it('calls handleBio on bio TextField change', () => {
render();
const input = screen.getByLabelText('bio');
fireEvent.change(input, { target: { value: 'new value' } });
expect(props.handleBio).toHaveBeenCalledTimes(1);
}
});