You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Jest编写测试用例覆盖依赖AppContext的React useEffect逻辑

测试实现方案

我们使用React Testing Library + Jest的通用技术栈完成测试,核心思路是模拟useAppContext自定义Hook的返回值,主动控制依赖项nextData的输入,验证useEffect触发后的组件行为是否符合预期,具体实现如下:


1. 前置准备

首先确保已安装测试依赖:

npm install @testing-library/react @testing-library/jest-dom jest -D

2. 可测试性改造(可选,推荐)

原组件的topic状态和generateEmail逻辑为内部私有,为了避免测试侵入内部实现,建议给渲染的按钮增加测试专用属性,方便直接断言结果:

return (
  <a
    download="meeting.eml"
    onClick={generateEmail}
    data-testid="send-email-btn"
    data-topic-list={JSON.stringify(topics)}
  >
    send
  </a>
);

3. 编写测试用例

测试覆盖3个核心场景:

  • 初始渲染时useEffect正常触发,正确过滤出flag=false的主题
  • nextData更新时useEffect重新触发,主题列表同步更新
  • 点击发送按钮时,能拿到正确的第一个主题

测试代码示例:

import { render, screen, fireEvent } from '@testing-library/react';
import { ShareEmail } from './ShareEmail';
// 替换为你项目中useAppContext的实际存放路径
import { useAppContext } from './app-context';

// 模拟自定义Hook,控制nextData的返回值
jest.mock('./app-context');
const mockUseAppContext = useAppContext as jest.Mock;

describe('ShareEmail组件useEffect逻辑测试', () => {
  // 每次用例执行前清空mock缓存
  beforeEach(() => jest.clearAllMocks());

  test('初始渲染时useEffect触发,正确过滤未标记的主题', () => {
    const mockNextData = [
      { id: 1, name: '需求评审', flag: false },
      { id: 2, name: '已归档主题', flag: true },
      { id: 3, name: '迭代排期', flag: false },
    ];
    mockUseAppContext.mockReturnValue({ nextData: mockNextData });

    render(<ShareEmail />);

    const sendBtn = screen.getByTestId('send-email-btn');
    const topicList = JSON.parse(sendBtn.getAttribute('data-topic-list'));
    // 断言过滤结果符合预期:只保留flag为false的2条
    expect(topicList.length).toBe(2);
    expect(topicList[0].name).toBe('需求评审');
  });

  test('nextData更新时useEffect重新触发,主题列表同步更新', () => {
    // 首次渲染传入旧数据
    mockUseAppContext.mockReturnValue({
      nextData: [{ id: 1, name: '旧主题', flag: false }]
    });
    const { rerender } = render(<ShareEmail />);

    // 模拟nextData更新,重新渲染组件
    mockUseAppContext.mockReturnValue({
      nextData: [{ id: 2, name: '新主题', flag: false }]
    });
    rerender(<ShareEmail />);

    const sendBtn = screen.getByTestId('send-email-btn');
    const topicList = JSON.parse(sendBtn.getAttribute('data-topic-list'));
    // 断言主题列表已更新为新数据
    expect(topicList.length).toBe(1);
    expect(topicList[0].name).toBe('新主题');
  });

  test('点击发送按钮时,正确取到第一个主题', () => {
    // 这里可以根据你实际generateEmail的业务逻辑扩展断言,比如验证生成的邮件内容、下载链接等
    const mockNextData = [{ id: 1, name: '测试主题', flag: false }];
    mockUseAppContext.mockReturnValue({ nextData: mockNextData });
    render(<ShareEmail />);

    // 模拟点击发送
    fireEvent.click(screen.getByTestId('send-email-btn'));
    // 补充你的业务逻辑断言即可
  });
});

内容的提问来源于stack exchange,提问作者prabhakaran s

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 13:06:01