问题描述
我正在尝试模拟将数据检索到组件中的 fetch().
I'm trying to mock a fetch() that retrieves data into a component.
我'我使用它作为模拟我的提取的模型,但我无法让它工作.
我在运行测试时收到此错误:babel-plugin-jest-hoist:jest.mock()"的模块工厂不允许引用任何范围外的变量.
I'm getting this error when I run my tests: babel-plugin-jest-hoist: The module factory of 'jest.mock()' is not allowed to reference any out-of-scope variables.
有没有办法让这些函数返回模拟数据,而不是实际尝试进行真正的 API 调用?
Is there a way I can have these functions return mock data instead of actually trying to make real API calls?
返回具有映射到每个用户的角色的用户.
Returns users with roles mapped into each user.
const getUsersWithRoles = rolesList =>
fetch(`/users`, {
credentials: "include"
}).then(response =>
response.json().then(d => {
const newUsersWithRoles = d.result.map(user => ({
...user,
roles: rolesList.filter(role => user.roles.indexOf(role.iden) !== -1)
}));
return newUsersWithRoles;
})
);
组件/UserTable.js
const UserTable = () => {
const [users, setUsers] = useState([]);
useEffect(() => {
getTableData();
}, []);
const getTableData = () => {
new Promise((res, rej) => res(getRoles()))
.then(roles => getUsersWithRoles(roles))
.then(users => {
setUsers(users);
});
};
return (...)
};
组件/测试/UserTable.test.js
component/tests/UserTable.test.js
import "jest-dom/extend-expect";
import React from "react";
import { render } from "react-testing-library";
import UserTable from "../UserTable";
import { getRoles as mockGetRoles } from "../utils/roleUtils";
import { getUsersWithRoles as mockGetUsersWithRoles } from "../utils/userUtils";
const users = [
{
name: "Benglish",
iden: "63fea823365f1c81fad234abdf5a1f43",
roles: ["eaac4d45c3c41f449cf7c94622afacbc"]
}
];
const roles = [
{
iden: "b70e1fa11ae089b74731a628f2a9b126",
name: "senior dev"
},
{
iden: "eaac4d45c3c41f449cf7c94622afacbc",
name: "dev"
}
];
const usersWithRoles = [
{
name: "Benglish",
iden: "63fea823365f1c81fad234abdf5a1f43",
roles: [
{
iden: "eaac4d45c3c41f449cf7c94622afacbc",
name: "dev"
}
]
}
];
jest.mock("../utils/userUtils", () => ({
getUsers: jest.fn(() => Promise.resolve(users))
}));
jest.mock("../utils/roleUtils", () => ({
getRolesWithUsers: jest.fn(() => Promise.resolve(usersWithRoles)),
getRoles: jest.fn(() => Promise.resolve(roles))
}));
test("<UserTable/> show users", () => {
const { queryByText } = render(<UserTable />);
expect(queryByText("Billy")).toBeTruthy();
});
推荐答案
默认情况下 jest.mock
调用由 babel-jest
...
By default jest.mock
calls are hoisted by babel-jest
...
...这意味着它们在您的测试文件中的任何其他内容之前运行,因此测试文件中声明的任何变量都不会在范围内.
...this means they run before anything else in your test file, so any variables declared in the test file won't be in scope yet.
这就是为什么传递给 jest.mock
的模块工厂不能引用自身之外的任何东西.
That is why the module factory passed to jest.mock
can't reference anything outside itself.
一种选择是将数据内部移动到模块工厂中,如下所示:
One option is to move the data inside the module factory like this:
jest.mock("../utils/userUtils", () => {
const users = [ /* mock users data */ ];
return {
getUsers: jest.fn(() => Promise.resolve(users))
};
});
jest.mock("../utils/roleUtils", () => {
const roles = [ /* mock roles data */ ];
const usersWithRoles = [ /* mock usersWithRoles data */ ];
return {
getRolesWithUsers: jest.fn(() => Promise.resolve(usersWithRoles)),
getRoles: jest.fn(() => Promise.resolve(roles))
};
});
另一种选择是使用 jest.spyOn
模拟函数:
import * as userUtils from '../utils/userUtils';
import * as roleUtils from '../utils/roleUtils';
const users = [ /* mock users data */ ];
const roles = [ /* mock roles data */ ];
const usersWithRoles = [ /* mock usersWithRoles data */ ];
const mockGetUsers = jest.spyOn(userUtils, 'getUsers');
mockGetUsers.mockResolvedValue(users);
const mockGetRolesWithUsers = jest.spyOn(roleUtils, 'getRolesWithUsers');
mockGetRolesWithUsers.mockResolvedValue(usersWithRoles);
const mockGetRoles = jest.spyOn(roleUtils, 'getRoles');
mockGetRoles.mockResolvedValue(roles);
另一个选项是自动模拟模块:
And another option is to auto-mock the modules:
import * as userUtils from '../utils/userUtils';
import * as roleUtils from '../utils/roleUtils';
jest.mock('../utils/userUtils');
jest.mock('../utils/roleUtils');
const users = [ /* mock users data */ ];
const roles = [ /* mock roles data */ ];
const usersWithRoles = [ /* mock usersWithRoles data */ ];
userUtils.getUsers.mockResolvedValue(users);
roleUtils.getRolesWithUsers.mockResolvedValue(usersWithRoles);
roleUtils.getRoles.mockResolvedValue(roles);
...并将模拟的响应添加到空的模拟函数中.
...and add the mocked response to the empty mock functions.
这篇关于如何模拟在使用 Jest 测试的 React 组件中进行的 API 调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!