NextJS v12.2.0 在运行 JEST 测试时导致路由器空引用问题

Dam*_*ian 1 unit-testing reactjs jestjs next.js

问题

\n

我正在从 NextJS v12.1.6 升级到 v12.2.2,除了一个测试文件之外的所有文件均已成功升级。

\n

运行BreadcrumbTrail测试套件时,下面包含的测试会破坏路由。该问题表明您无法推送到空对象;这是有道理的,但调试后一切看起来都正常。还有一个次要问题,但我相信这是由空引用错误(无论如何都包含在内)引起的级联问题。

\n

问题

\n
    \n
  • 有人在 v12.2.0 中遇到过路由错误吗?
  • \n
  • 有人对解决这个问题有建议吗?
  • \n
\n

基本堆栈详细信息

\n
    \n
  • 反应 v18.2.0
  • \n
  • 下一个v12.2.0
  • \n
  • 玩笑 v28.1.1
  • \n
\n

尝试的解决方案/阅读

\n

在 v12.2.0 之前,此测试顺利通过。

\n

据我所知,PR 36660解决了由于竞争条件导致的问题asPath,但现在可能导致我们当前的问题。

\n

测试代码

\n
import { render, screen, within, waitFor } from "@testing-library/react";\nimport singletonRouter from "next/router";\nimport mockRouter from "next-router-mock";\nimport userEvent from "@testing-library/user-event";\nimport { BreadcrumbTrail } from "./BreadcrumbTrail";\n\njest.mock("next/dist/client/router", () => require("next-router-mock"));\n\nconst navPath = "/some-navpath";\n\ndescribe("BreadcrumbTrail", function () {\n  beforeEach(() => {\n    mockRouter.setCurrentUrl(navPath);\n  });\n\n  it("navigates to the correct location when clicking on a crumb", async function () {\n    render(<BreadcrumbTrail />);\n    const breadcrumbs = screen.getByRole("list", { name: /breadcrumbs/i });\n    const { getByText } = within(breadcrumbs);\n    const breadcrumb = getByText("Foo");\n\n    await userEvent.click(breadcrumb);\n\n    await waitFor(() =>\n      expect(singletonRouter).toMatchObject({\n        asPath: "/someother-navpath",\n      }),\n    );\n  });\n});\n
Run Code Online (Sandbox Code Playgroud)\n

错误一

\n
FAIL  components/Navigation/BreadcrumbTrail.test.tsx\n\nConsole\n\n console.error\n   Error: Uncaught [TypeError: Cannot read property \'push\' of null]\n\n...\n...\n...\n\nEventTarget.js:241:34)\n   at dispatchEvent (/<Repository Path>/node_modules/@testing-library/user-event/dist/index.cjs:1716:33)\n   at /<Repository Path>/node_modules/@testing-library/react/dist/pure.js:125:16\n   at /<Repository Path>/node_modules/@testing-library/react/dist/act-compat.js:110:24\n   at act (/<Repository Path>/node_modules/react/cjs/react.development.js:2457:20) {\n     detail: TypeError: Cannot read property \'push\' of null\n        at navigate (/<Repository Path>/node_modules/next/dist/client/link.js:90:11)\n        at linkClicked (/<Repository Path>/node_modules/next/dist/client/link.js:100:5)\n        at onClick (/<Repository Path>/node_modules/next/dist/client/link.js:330:9)\n        at HTMLUnknownElement.callCallback (/<Repository Path>/node_modules/react-dom/cjs/react-dom.development.js:730:119)\n\n...\n...\n...\n\nBreadcrumbTrail \xe2\x80\xba navigates to the correct location when clicking on a crumb\n\n    TypeError: Cannot read property \'push\' of null\n\n      40 |     const breadcrumb = getByText("Foo");\n      41 |\n    > 42 |     await userEvent.click(breadcrumb);\n
Run Code Online (Sandbox Code Playgroud)\n

错误二

\n
expect(received).toMatchObject(expected)\n\n- Expected  - 1\n+ Received  + 1\n\nObject {\n-   "asPath": "/someother-navpath",\n+   "asPath": "/some-navpath",\n}\n
Run Code Online (Sandbox Code Playgroud)\n

Dam*_*ian 5

这是next-router-mock中的一个问题;由于 NextJS 中路由管理方式的重大变化,该包已损坏。

来源:Next 12.2.0 中的 next/link 问题

以下代码应该可以解决该问题

jest.mock("next/dist/client/router", () => require("next-router-mock"));

jest.mock("next/dist/shared/lib/router-context", () => {
  const { createContext } = require("react");
  const router = require("next-router-mock").default;
  const RouterContext = createContext(router);
  return { RouterContext };
});
Run Code Online (Sandbox Code Playgroud)