问题描述
我正在尝试在 Apollo Client 的玩笑测试中使用 graphql-tools
的 addMocksToSchema
函数,以允许我通过返回我可以为自己定义的模拟数据来测试查询 Apollo 的组件。但是,使用 useQuery
时无法正确返回模拟数据。
我有一个 UserButton
按钮,我正在尝试为其编写测试。组件如下:
// UserButton.jsx
import React from "react";
import PropTypes from "prop-types";
import { gql } from "@apollo/client";
import { useQuery } from "@apollo/client";
import Button from "./Button";
const GET_CURRENT_USER = gql`
query GetCurrentUser {
id
firstName
lastName
}
`;
function UserButton({ ...props }) {
const { data: userData } = useQuery(GET_CURRENT_USER);
return <Button {...props}>{userData.firstName} {userData.lastName}'s Button</Button>;
}
UserButton.propTypes = {
children: PropTypes.node,};
export default UserButton;
这是我的测试:
// UserButton.test.jsx
import React from "react";
import { render,screen } from "@testing-library/react";
import UserButton from "../UserButton";
import ApolloMockingProvider from "../../providers/ApolloMockingProvider";
import userEvent from "@testing-library/user-event";
import { debug } from "webpack";
describe("UserButton",() => {
let onClickMock;
beforeEach(() => {
jest.resetAllMocks();
onClickMock = jest.fn();
});
it("Renders with first and last name.",() => {
render(
<ApolloMockingProvider>
<UserButton />
</ApolloMockingProvider>
);
const button = screen.getByRole("button");
expect(button).toHaveTextContent("John Smith's Button")
});
});
ApolloMockingProvider
基于 following article,其代码如下:
// ApolloMoockingProvider.jsx
import {
ApolloClient,ApolloProvider,InMemoryCache,} from "@apollo/client";
import { SchemaLink } from "@apollo/client/link/schema";
import { addMocksToSchema } from "@graphql-tools/mock";
import { makeExecutableSchema } from "@graphql-tools/schema";
import React from "react";
const schemaString = `
type AvatarObjectType {
id: Int,avatarUrl: String
}
scalar DateTime
scalar GenericScalar
type UserObjectType {
id: Int,username: String,firstName: String,lastName: String,avatar: AvatarObjectType,dateCreated: DateTime,notificationPreferences: GenericScalar,}
type Query {
GetCurrentUser: UserObjectType,}
`;
const globalMocks = {
String: () => "abc",Int: () => 56,UserObjectType: () => ({
firstName: "John",lastName: "Smith",}),};
const ApolloMockingProvider = ({ children }) => {
const executableSchema = makeExecutableSchema({ typeDefs: schemaString });
const schemaWithMocks = addMocksToSchema({
schema: executableSchema,mocks: globalMocks,});
const client = new ApolloClient({
link: new SchemaLink({ schemaWithMocks }),cache: new InMemoryCache(),});
return <ApolloProvider client={client}>{children}</ApolloProvider>;
};
export default ApolloMockingProvider;
传入 ApolloMockingProvider
的 globalMock
的 schemaWithMocks
对象应该为 UserButton
的 Renders with first and last name.
测试返回“John Smith 的按钮”。但是,如此错误消息所示,我对 userData
未定义:
UserButton › Renders with first and last name.
TypeError: Cannot read property 'firstName' of undefined
16 | function UserButton({ ...props }) {
17 | const { data: userData } = useQuery(GET_CURRENT_USER);
> 18 | return <Button {...props}>{userData.firstName} {userData.lastName}'s Button</Button>;
| ^
19 | }
20 |
21 | UserButton.propTypes = {
at UserButton (js/components/button/UserButton.jsx:18:39)
有人知道这里的错误是什么吗?复制 repo is here,失败的测试为 located here:
编辑:
我在 UserButton 的 loading
中添加了 useQuery
,但仍然出现相同的 undefined
错误。
// UserButton.test.jsx
function UserButton({ ...props }) {
const { data: userData,loading } = useQuery(GET_CURRENT_USER);
let buttonText = "Loading...";
if (!loading) {
buttonText = `${userData.firstName} ${userData.lastName}'s Button`;
}
return <Button {...props}>{buttonText}</Button>;
}
并相应地更改了 UserButton.test.jsx
测试:
it("Renders with first and last name.",async () => {
render(
<ApolloMockingProvider>
<UserButton />
</ApolloMockingProvider>
);
const button = screen.getByRole("button");
expect(button).toHaveTextContent("Loading...")
await waitFor(() => {
expect(screen.queryByText("John Smith's Button")).toBeInTheDocument();
});
});
但我得到的错误仍然是 userData
为 undefined
UserButton › Renders with first and last name.
TypeError: Cannot read property 'firstName' of undefined
19 |
20 | if (!loading) {
> 21 | buttonText = `${userData.firstName} ${userData.lastName}'s Button`;
| ^
22 | }
23 | return <Button {...props}>{buttonText}</Button>;
24 | }
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)