@remix-run/testing
此软件包包含一些实用程序,可帮助你对 Remix 应用的各个部分进行单元测试。这是通过模拟编译器输出的 Remix 路由模块/资源清单,并通过 createMemoryRouter 生成一个内存中的 React Router 应用来实现的。
¥This package contains utilities to assist in unit testing portions of your Remix application. This is accomplished by mocking the Remix route modules/assets manifest output by the compiler and generating an in-memory React Router app via createMemoryRouter.
此方法的一般用途是测试依赖于 Remix 钩子/组件的组件/钩子,而这些钩子/组件你无法干净地模拟(useLoaderData
、useFetcher
等)。虽然它也可以用于更高级的测试,例如点击链接和导航到页面,但这些测试更适合通过 Cypress 或 Playwright 之类的方式进行端到端测试。
¥The general usage of this is to test components/hooks that rely on Remix hooks/components which you aren't able to cleanly mock (useLoaderData
, useFetcher
, etc.). While it can also be used for more advanced testing such as clicking links and navigating to pages, those are better suited for End-to-End tests via something like Cypress or Playwright.
¥Usage
要使用 createRemixStub
,请使用类似 React Router 的路由对象定义你的路由,并在其中指定 path
、Component
、loader
等。这些本质上是在模拟 Remix 应用中路由文件的嵌套和导出:
¥To use createRemixStub
, define your routes using React Router-like route objects, where you specify the path
, Component
, loader
, etc. These are essentially mocking the nesting and exports of the route files in your Remix app:
import { createRemixStub } from "@remix-run/testing";
const RemixStub = createRemixStub([
{
path: "/",
Component: MyComponent,
loader() {
return json({ message: "hello" });
},
},
]);
然后,你可以渲染 <RemixStub />
组件并对其进行断言:
¥Then you can render the <RemixStub />
component and assert against it:
render(<RemixStub />);
await screen.findByText("Some rendered text");
¥Example
以下是使用 jest
和 React 测试库 进行测试的完整工作示例:
¥Here's a full working example testing using jest
and React Testing Library:
import { json } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";
import { createRemixStub } from "@remix-run/testing";
import {
render,
screen,
waitFor,
} from "@testing-library/react";
test("renders loader data", async () => {
// ⚠️ This would usually be a component you import from your app code
function MyComponent() {
const data = useLoaderData() as { message: string };
return <p>Message: {data.message}</p>;
}
const RemixStub = createRemixStub([
{
path: "/",
Component: MyComponent,
loader() {
return json({ message: "hello" });
},
},
]);
render(<RemixStub />);
await waitFor(() => screen.findByText("Message: hello"));
});