javascript - 使用返回承诺的玩笑模拟 axios 不起作用
问题描述
我试图嘲笑我的 axios 进入 Jest。我是反应测试的新手,所以请善待
我已经按照本教程和这个答案进行了操作,我想我已经掌握了该怎么做。基本上在组件安装时,我在我的UseEffect
.
这是不工作的测试:
jest.mock("axios");
describe("User form async tests", () => {
it("Renders widget", async (done) => {
const promiseRole = new Promise((resolve, reject) =>
┊ setTimeout(
┊ ┊ () =>
┊ ┊ ┊ resolve({
┊ ┊ ┊ ┊ data: [
┊ ┊ ┊ ┊ ┊ { id: 0, name: "Admin" },
┊ ┊ ┊ ┊ ┊ { id: 1, name: "Editor" },
┊ ┊ ┊ ┊ ],
┊ ┊ ┊ }),
┊ ┊ 100
┊ )
);
const promiseLocs = new Promise((resolve, reject) =>
┊ setTimeout(
┊ ┊ () =>
┊ ┊ ┊ resolve({
┊ ┊ ┊ ┊ data: [
┊ ┊ ┊ ┊ ┊ { id: 0, name: "Loc1" },
┊ ┊ ┊ ┊ ┊ { id: 1, name: "Loc2" },
┊ ┊ ┊ ┊ ],
┊ ┊ ┊ }),
┊ ┊ 100
┊ )
);
┊ axios.get.mockImplementationOnce(() => promiseRole);
┊ axios.get.mockImplementationOnce(() => promiseLocs);
┊ const wrapper = mount(<UserForm />);
┊ await promiseRole;
┊ await promiseLocs;
┊ setImmediate(() => {
┊ ┊ wrapper.update();
┊ ┊ expect(wrapper.contains(Widget)).toEqual(true);
┊ ┊ done();
┊ });
});
});
不知何故,它总是为小部件返回 false。获取数据后,我所做的就是将状态设置为就绪,因此它将呈现 Widget 组件。有趣的是,如果我直接将代码更改为 mockResolvedValue,那么它就可以工作。我不明白为什么上面的代码不起作用?基本上它也解决了相同的值......有人可以帮忙吗?我真的很困惑,无法解决这个问题,这真的让我很困扰
如果 axios 返回正确的数据,有一个代码调用
setReady(true)
,因此它返回<Widget ... />
后
谢谢
工作测试,因为我嘲笑了每个 get 请求:
jest.mock("axios");
describe("User form async tests", () => {
it("Renders widget", async (done) => {
┊ const location = [{ id: 0, name: "hurstville" }];
┊ const resp = { data: location };
┊ axios.get.mockResolvedValue(resp);
┊ const wrapper = mount(<UserForm />);
┊ setImmediate(() => {
┊ ┊ wrapper.update();
┊ ┊ expect(wrapper.contains(Widget)).toEqual(true);
┊ ┊ done();
┊ });
});
});
在UserForm
我使用的组件中formik
和material-ui
. 所以问题在于它期望
在组件中提供数据类型以供选择的getData()
功能。useEffect
[{id: PropTypes.number, name: PropTypes.string}]
<FormikSelect />
因此第二个工作测试有效
用户窗体:
import React, { useEffect, useState } from "react";
import {
FormikTextField,
FormikArray,
FormikSelect,
} from "app/components/forms/Utils";
import { FormikTransferList, Widget, Alert } from "app/components";
import { Formik, Form, ErrorMessage } from "formik";
import {
getUserById,
getUserRole,
addUser,
getLocationList,
updateUser,
} from "app/crud/user.crud";
import {
formValues,
validationUser,
} from "app/components/forms/users/UserConst";
import { useLocation, useHistory } from "react-router-dom";
import FuseSplashScreen from "@fuse/core/FuseSplashScreen";
import { Snackbar, Button } from "@material-ui/core";
const processedLocs = (data) =>
data.map((item) => {
return {
...item,
key: item.id,
title: item.name,
};
});
function UserForm() {
const [initial, setFormValues] = useState(formValues);
const location = useLocation();
const history = useHistory();
const [roles, setRoles] = useState([]);
const [locationList, setLocationList] = useState([]);
const [ready, setReady] = useState(false);
const [open, setOpen] = useState(false);
useEffect(() => {
async function getData() {
try {
const response = await getUserRole();
const locresult = await getLocationList();
if (response) {
setRoles(response.data);
setLocationList(processedLocs(locresult.data));
setReady(true);
}
} catch (err) {
console.log(err.message);
}
}
getData();
}, [getUserRole]);
useEffect(() => {
async function getUserDetails(id) {
const response = await getUserById(id);
if (response) {
const newVal = {
...response.data,
roles: response.data.roles.map((item) => ({
...item,
locations: item.locations.map((loc) => loc.id),
})),
};
setFormValues(newVal);
} else {
setFormValues(formValues);
}
}
if (location.state && location.state.id) {
getUserDetails(location.state.id);
}
}, [location.state]);
const handleCloseAlert = (event, reason) => {
if (reason === "clickaway") {
return;
}
setOpen(false);
};
const handleSuccess = () => {
setOpen(true);
};
return ready ? (
<>
<Formik
enableReinitialize
initialValues={initial}
validationSchema={validationUser}
onSubmit={async (
values,
{ setSubmitting, setErrors, setStatus, resetForm }
) => {
setTimeout(async () => {
try {
let response;
if (location.state && location.state.id) {
response = await updateUser(values.id, values);
} else {
response = await addUser(values);
if (response) {
handleSuccess();
}
}
resetForm(formValues);
history.goBack();
setStatus({ success: true });
} catch (err) {
setSubmitting(false);
setErrors({ submit: err.message });
}
}, 200);
}}
>
<Form>
<div className="container grid grid-cols-1 gap-4 p-8">
<Widget title="User Details" containerClass="p-8">
<div className="grid grid grid-cols-1 gap-4">
<FormikTextField
id="name"
variant="outlined"
name="name"
label="Full Name"
/>
<FormikTextField
id="email"
variant="outlined"
name="email"
label="Email Address"
/>
<FormikTextField
id="phone"
variant="outlined"
name="phone"
label="Phone number"
/>
</div>
</Widget>
<Widget title="User Roles" containerClass="p-8">
<div className="flex flex-col p-8">
<ErrorMessage
name="roles"
render={(msg) => (
<div className="text-lg text-red-600 p-8 ml-8">{msg}</div>
)}
/>
<FormikArray name="roles" defaultValue={initial.roles[0]}>
{({ index }) => (
<div className="flex flex-col p-8 mb-8">
<div>
<p className="text-lg font-semibold text-blue-400">
Assign locations to the role of the user. Each user
can has multiple locations based on the role that they
have
</p>
</div>
<div>
<p className="text-lg font-medium">Role {index + 1} </p>
</div>
<FormikSelect
labelId={`rolesSelectLabel${index}`}
options={roles}
label="Select Roles"
selectId={`rolesSelect${index}`}
name={`roles.${index}.id`}
/>
<div>
<p className="text-lg font-medium">Put Location:</p>
</div>
<div className="w-full">
<FormikTransferList
options={locationList}
name={`roles.${index}.locations`}
/>
</div>
</div>
)}
</FormikArray>
</div>
<div className="w-1/2 p-8">
<Button variant="contained" color="primary" type="submit">
{location.state && location.state.id ? "Update" : "Submit"}
</Button>
</div>
</Widget>
</div>
</Form>
</Formik>
<Snackbar open={open} autoHideDuration={4000} onClose={handleCloseAlert}>
<Alert onClose={handleCloseAlert} severity="success">
User Created
</Alert>
</Snackbar>
</>
) : (
<FuseSplashScreen />
);
}
UserForm.propTypes = {};
export default UserForm;