React:如何模拟 Auth0 以使用 Jest 进行测试

React: How to mock Auth0 for testing with Jest

我正在使用 React(react-create-app 和 TypeScript)。使用 Auth0 登录。

我想用 Jest 编写测试,我发现这个资源基本上是唯一一个关于模拟 Auth0 对象的资源。

所以我的代码是这样的:

import React from "react";
import ReactDOM from "react-dom";
import TopBar from "./index";
import {
  useAuth0
} from "react-auth0-spa";

const user = {
  email: "johndoe@me.com",
  email_verified: true,
  sub: "google-oauth2|12345678901234"
};

// intercept the useAuth0 function and mock it
jest.mock("react-auth0-spa");

describe("First test", () => {
  beforeEach(() => {
    // Mock the Auth0 hook and make it return a logged in state
    useAuth0.mockReturnValue({
      isAuthenticated: true,
      user,
      logout: jest.fn(),
      loginWithRedirect: jest.fn()
    });
  });

  it("renders without crashing", () => {
    const div = document.createElement("div");
    ReactDOM.render( < TopBar / > , div);
  });
});

但我最终遇到了这个错误:

Property 'mockReturnValue' does not exist on type '() => IAuth0Context | undefined'.ts(2339)

我在这里有点迷路,任何帮助将不胜感激!

这是一个 TypeScript 错误。您将需要键入模拟的 useAuth0,因为原始类型没有名为 mockReturnValue 的方法。这样的事情应该有效:

const mockedUseAuth0 = <jest.Mock<typeof useAuth0>>useAuth0;

mockedUseAuth0.mockReturnValue({
  isAuthenticated: true,
  user,
  logout: jest.fn(),
  loginWithRedirect: jest.fn()
});

我自己花了一个小时左右的时间来解决这个问题。问题源于在修改 mock return 值后应用于 useAuth0 的类型不正确。我的解决方案是使用来自 'ts-jest/utils' 的模拟。您还可以向用户对象添加角色、范围等。 (查看 adminUser 对象)

import { render, screen } from "@testing-library/react";
import { useAuth0 } from "@auth0/auth0-react";
import { mocked } from "ts-jest/utils";

const user = {
    email: "johndoe@me.com",
    email_verified: true,
    sub: "google-oauth2|12345678901234",
};

const adminUser = {
    email: "johndoe@me.com",
    email_verified: true,
    sub: "google-oauth2|12345678901234",
    "https://<<API_URL>>/roles": ["admin", "superuser"],
};


jest.mock("@auth0/auth0-react");

const mockedUseAuth0 = mocked(useAuth0, true);

describe("TopNav Component Tests - Logged in", () => {
    beforeEach(() => {
        mockedUseAuth0.mockReturnValue({
            isAuthenticated: true,
            user,
            logout: jest.fn(),
            loginWithRedirect: jest.fn(),
            getAccessTokenWithPopup: jest.fn(),
            getAccessTokenSilently: jest.fn(),
            getIdTokenClaims: jest.fn(),
            loginWithPopup: jest.fn(),
            isLoading: false,
        });
    });
    test("Logout Button displays when logged in", () => {
        render(
                <TopNav />
        );
        const loginButton = screen.getByText(/Logout/i);
        expect(loginButton).toBeInTheDocument();
    });
    test("Make sure Admin Panel Button doesnt show without Role", () => {
        render(
                <TopNav />
        );
        const adminPanelButton = screen.queryByText(/Admin Panel/i);
        expect(adminPanelButton).toBeNull();
    });
});

describe("TopNav Component Tests - Admin User", () => {
    beforeEach(() => {
        mockedUseAuth0.mockReturnValue({
            isAuthenticated: true,
            user: adminUser,
            logout: jest.fn(),
            loginWithRedirect: jest.fn(),
            getAccessTokenWithPopup: jest.fn(),
            getAccessTokenSilently: jest.fn(),
            getIdTokenClaims: jest.fn(),
            loginWithPopup: jest.fn(),
            isLoading: false,
        });
    });
    test("Admin Panel Button displays", () => {
        render(
            <TopNav />
        );
        const adminPanelButton = screen.getByText(/Admin Panel/i);
        expect(adminPanelButton).toBeInTheDocument();
    });
});