我已经通过使用异步
it
成功测试了一个隔离的服务器组件,并等待组件调用的输出作为普通函数传递到渲染中:
it('renders the user data when user is authenticated', async () => {
render(await UserData())
expect(screen.getByTestId('user-data')).toBeInTheDocument();
});
^ 有效并通过。
但我还有一个 page.tsx 服务器组件,它呈现另一个服务器组件 -
<UserData />
- 嵌套在其中:
'use server'
import styles from './page.module.css';
import LogInOut from "./LogInOut/LogInOut";
import UserData from "./UserData";
export default async function Page() {
return (
<main className={styles.main}>
<h1>Title</h1>
<LogInOut/>
<UserData />
</main>
);
}
// Note: LogInOut is a client component, removing it doesn't help the problem.
...如果我尝试相同的技术来测试这个组件,即:
it('renders a heading', async () => {
render(await Page());
const heading = screen.getByRole('heading', { level: 1 });
expect(heading).toBeInTheDocument();
});
^ ...这不起作用——我收到一条错误消息:
错误:未捕获[错误:对象作为 React 子对象无效(发现: [对象承诺])。如果你想渲染一组孩子, 请改用数组。]
我们如何测试嵌套的服务器组件? 我想要一种解决方案,允许我在单元测试中渲染父服务器组件和后代服务器组件,而无需模拟其中一个或另一个。
似乎对 react-testing-library 的支持不多,请参见这里。使用
Suspense
怎么样,你尝试过吗?
import { render, screen } from "@testing-library/react";
import { Suspense } from "react";
it('renders a heading', async () => {
render(
<Suspense>
<Page />
</Suspense>
);
const heading = await screen.getByRole('heading', { level: 1 });
expect(heading).toBeInTheDocument();
});
React 测试库的Issue 1209的讨论仍在进行中:
您遇到的错误是因为您尝试使用await异步渲染React组件,但渲染函数需要同步组件。
试试这个方法:
it('renders a heading', async () => {
const page = await Page(); // Resolve the promise before rendering
render(page);
const heading = screen.getByRole('heading', { level: 1 });
expect(heading).toBeInTheDocument();
});