我正在尝试在 Apollo Client 的开玩笑测试中使用graphql-tools
'saddMocksToSchema
函数,以允许我通过返回我可以为自己定义的模拟数据来测试查询 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
基于以下文章,其代码如下:
// 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
为'测试返回 'John Smith's Button' 。但是,相反,我得到了未定义的错误消息,如下所示:globalMock
schemaWithMocks
UserButton
Renders with first and last name.
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 在这里,失败的测试位于这里:
编辑:
我添加loading
到useQuery
in UserButton 但仍然得到相同的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 | }