在玩笑测试中使用 graphql-tools 的 addMocksToSchema 不适用于来自“@apollo/client”的 gql

问题描述

我正在尝试在 Apollo Client 的玩笑测试中使用 graphql-toolsaddMocksToSchema 函数,以允许我通过返回我可以为自己定义的模拟数据来测试查询 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;

传入 ApolloMockingProviderglobalMockschemaWithMocks 对象应该为 UserButtonRenders 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();
    });
  });

但我得到的错误仍然是 userDataundefined

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 (将#修改为@)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...