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

如何为含navigation.addListener的React Native useEffect编写单元测试

React Native RecipeScreen 单元测试实现

我们可以使用Jest和@testing-library/react-native编写这两个单元测试,核心思路是mock依赖的API函数和导航钩子,模拟不同场景并验证组件渲染结果。

前置准备

确保项目已安装必要测试依赖:

npm install --save-dev jest @testing-library/react-native @testing-library/jest-native

测试代码实现

创建测试文件RecipeScreen.test.js,编写如下逻辑:

import React from 'react';
import { render, waitFor } from '@testing-library/react-native';
import RecipeScreen from './RecipeScreen';
import { useNavigation } from '@react-navigation/native';
import { fetchRecipes } from './your-api-module'; // 替换为实际API模块路径

// Mock导航钩子与API函数
jest.mock('@react-navigation/native', () => ({
  useNavigation: jest.fn(),
}));
jest.mock('./your-api-module', () => ({
  fetchRecipes: jest.fn(),
}));

describe('RecipeScreen', () => {
  const mockAddListener = jest.fn((event, callback) => {
    // 模拟触发focus事件回调
    if (event === 'focus') callback();
    return jest.fn(); // 返回mock的unsubscribe函数
  });

  beforeEach(() => {
    // 重置所有mock
    jest.clearAllMocks();
    useNavigation.mockReturnValue({ addListener: mockAddListener });
  });

  // 测试API调用失败时显示Error组件
  it('renders Error component when API call fails', async () => {
    // Mock API返回错误
    fetchRecipes.mockResolvedValue({ error: true });

    const { getByTestId } = render(<RecipeScreen />);

    await waitFor(() => {
      // 需给Error组件添加testID="error-component"
      expect(getByTestId('error-component')).toBeTruthy();
    });
  });

  // 测试API调用成功时显示食谱列表
  it('renders recipe list when API call succeeds', async () => {
    // Mock API返回成功的食谱数据
    const mockRecipes = [
      { id: '1', title: '番茄炒蛋' },
      { id: '2', title: '酸辣土豆丝' },
    ];
    fetchRecipes.mockResolvedValue({ error: false, recipes: mockRecipes });

    const { getAllByTestId, queryByTestId } = render(<RecipeScreen />);

    await waitFor(() => {
      // 验证Error组件不存在
      expect(queryByTestId('error-component')).toBeNull();
      // 验证Recipe组件渲染数量匹配(需给Recipe组件添加testID="recipe-item")
      const recipeItems = getAllByTestId('recipe-item');
      expect(recipeItems).toHaveLength(mockRecipes.length);
    });
  });
});

关键说明

  • Mock导航逻辑:通过mockuseNavigation的addListener方法,直接触发focus事件回调,模拟屏幕聚焦行为。
  • Mock API函数:根据测试场景让fetchRecipes返回成功/失败的模拟数据,避免实际调用真实API。
  • 异步等待:使用waitFor确保异步的loadRecipes执行完成后再断言,避免测试过早执行导致结果不准确。
  • TestID设置:需给Error和Recipe组件添加testID属性,方便测试时定位元素。

内容的提问来源于stack exchange,提问作者Rupesh Ghosh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 19:07:51