tmo*_*mos 5 javascript typescript reactjs jestjs auth0
我正在使用 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);
});
});Run Code Online (Sandbox Code Playgroud)
但我最终陷入了这个错误:
Property 'mockReturnValue' does not exist on type '() => IAuth0Context | undefined'.ts(2339)
我在这里有点迷茫,任何帮助将不胜感激!
小智 12
我自己花了一个小时左右解决这个问题。问题源于修改模拟返回值后应用于 useAuth0 的错误类型。我的解决方案是使用“ts-jest/utils”中的模拟。您还可以将角色、范围等添加到用户对象。(参见 adminUser 对象)
更新 2022-11-21自版本 28.0+ 起,该mocked功能已从软件包中删除(请参阅v27 文档)ts-jestmocked
该函数现已弃用,并将在28.0.0中删除。该功能已作为 Jest 27.4.0
jest-mock的一部分集成到包中,请参阅https://github.com/facebook/jest/pull/12089。请使用来自的替代。jest-mock
import { render, screen } from "@testing-library/react";
import { useAuth0 } from "@auth0/auth0-react";
// if you're using jest 27.4.0+ and ts-jest 28.0.0+
import { mocked } from "jest-mock";
// if you're using ts-jest < 28.0.0
// 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();
});
});
Run Code Online (Sandbox Code Playgroud)
阅读这篇文章后,遇到类似的错误,并更仔细地调查笑话文档......
我能够在使用正常的 Auth0 导入和标准 jest 模拟功能时模拟 useAuth0() 挂钩。
如果此解决方案有改进或存在问题,请告诉我,因为我是使用 jest 的新手。
我所做的概述如下。在这个例子中,我使用 FooBar 作为 React 组件,并使用 FooBar.test.js 作为相应的 jest 测试脚本。
第 1 步:在 FooBar.test.js 中,创建一个可用于指示登录/注销的变量
// flag to switch between logged-in and logged-out, default to logged-out
let mockLoginStatus = false;
Run Code Online (Sandbox Code Playgroud)
第 2 步:在 FooBar.test.js 中,创建一个用户、登录和注销的值以及模拟 useAuth0 的函数
// mock user info
const auth0User = {
nickname: 'marydoe',
name: 'marydoe@gmail.com',
email: 'marydoe@gmail.com',
};
// value returned for useAuth0 when logged-in
const mockUseAuth0LoggedIn = {
isAuthenticated: true,
isLoading: false,
user: auth0User,
logout: jest.fn(),
loginWithRedirect: jest.fn()
};
// value returned for useAuth0 when logged-out
const mockUseAuth0LoggedOut = {
isAuthenticated: false,
isLoading: false,
user: null,
logout: jest.fn(),
loginWithRedirect: jest.fn()
};
// mock useAuth0 function that return logged-in or logged-out values
const mockUseAuth0 = (status) => {
if (status) {
return mockUseAuth0LoggedIn;
}
return mockUseAuth0LoggedOut;
};
Run Code Online (Sandbox Code Playgroud)
第 3 步:在 FooBar.test.js 中,设置 @auth0 库的模拟。仅模拟您需要模拟的功能,同时保留其他功能与原始模块相同。
jest.mock('@auth0/auth0-react', () => {
// load original module
const originalModule = jest.requireActual('@auth0/auth0-react');
// mock only the functions we want to mock
return {
__esModule: true,
...originalModule,
useAuth0: jest.fn(() => mockUseAuth0(mockLoginStatus))
};
});
Run Code Online (Sandbox Code Playgroud)
第 4 步:在 FooBar.test.js 中设置您的测试 beforeAll 和 afterAll 以根据您的意愿登录(或不登录)。
describe('FooBar component, authenticated', () => {
// login, authenticate
beforeAll(() => {
mockLoginStatus = true;
});
// logout
afterAll(() => {
mockLoginStatus = false;
});
test('FooBar contains foo bar', () => {
YOUR TEST CODE GOES HERE
});
Run Code Online (Sandbox Code Playgroud)
完成此操作后,在您拥有 useAuth0 的 React 组件 FooBar.js 中,它将正确模拟并调用您的 mockAuth0 函数并返回您上面定义的值。
如果您正在阅读本文并需要帮助,我希望这对您有所帮助,并且它也对您有用。:)
祝你一切顺利,
-加布里埃尔
这是一个打字稿错误。您将需要键入模拟,useAuth0因为原始类型没有称为mockReturnValue. 这样的事情应该工作:
const mockedUseAuth0 = <jest.Mock<typeof useAuth0>>useAuth0;
mockedUseAuth0.mockReturnValue({
isAuthenticated: true,
user,
logout: jest.fn(),
loginWithRedirect: jest.fn()
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3928 次 |
| 最近记录: |