如何使用Jest测试Next.js中的ClientPortal组件
ClientPortal 组件测试方案
核心测试场景
我们围绕组件的核心行为设计3个覆盖度足够的测试用例:
- 匹配指定选择器的DOM节点存在时,子元素正确渲染到该节点内
- 无匹配指定选择器的DOM节点时,不渲染任何内容
- 选择器参数更新时,子元素自动迁移到新选择器对应的DOM节点
完整测试代码
测试文件命名为 ClientPortal.test.jsx 即可,代码如下:
import { render, screen } from '@testing-library/react'; import ClientPortal from './ClientPortal'; describe('ClientPortal 组件', () => { // 每个用例执行后清空body内容,避免用例间相互影响 afterEach(() => { document.body.innerHTML = ''; }); test('存在匹配选择器的节点时,子元素渲染到目标节点内', () => { // 提前在jsdom中创建目标挂载节点 const targetNode = document.createElement('div'); targetNode.setAttribute('id', 'portal-root'); document.body.appendChild(targetNode); render( <ClientPortal selector="#portal-root"> <p>门户测试内容</p> </ClientPortal> ); const content = screen.getByText('门户测试内容'); expect(content).toBeInTheDocument(); expect(targetNode).toContainElement(content); }); test('无匹配选择器的节点时,不渲染任何内容', () => { const { container } = render( <ClientPortal selector="#not-exist-node"> <p>测试内容</p> </ClientPortal> ); expect(screen.queryByText('测试内容')).not.toBeInTheDocument(); expect(container.firstChild).toBeNull(); }); test('选择器参数更新时,子元素迁移到新的目标节点', () => { // 提前创建两个不同的挂载节点 const firstTarget = document.createElement('div'); firstTarget.setAttribute('id', 'first-portal'); const secondTarget = document.createElement('div'); secondTarget.setAttribute('id', 'second-portal'); document.body.append(firstTarget, secondTarget); // 首次渲染使用第一个选择器 const { rerender } = render( <ClientPortal selector="#first-portal"> <p>动态切换内容</p> </ClientPortal> ); const content = screen.getByText('动态切换内容'); expect(firstTarget).toContainElement(content); expect(secondTarget).not.toContainElement(content); // 更新选择器重新渲染 rerender( <ClientPortal selector="#second-portal"> <p>动态切换内容</p> </ClientPortal> ); // 校验内容已迁移到第二个节点 expect(secondTarget).toContainElement(content); expect(firstTarget).not.toContainElement(content); }); });
注意事项
- 该组件本身依赖浏览器
documentAPI,属于客户端组件,上述测试用例在Jest+jsdom环境下可直接运行,不需要额外模拟Next.js SSR相关能力 - 运行测试前请确保你已安装
@testing-library/jest-dom扩展,否则toBeInTheDocument、toContainElement等断言会报错
内容的提问来源于stack exchange,提问作者Akash
相关产品推荐
相关产品推荐

