0

我正在尝试在 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' 。但是,相反,我得到了未定义的错误消息,如下所示:globalMockschemaWithMocksUserButtonRenders 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 在这里,失败的测试位于这里

编辑:

我添加loadinguseQueryin 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();
    });
  });

但我得到的错误仍然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 | }
4

0 回答 0