首页
/ React Native Testing Library 网络请求测试指南

React Native Testing Library 网络请求测试指南

2025-07-10 02:13:14作者:邵娇湘

前言

在现代移动应用开发中,网络请求是不可避免的核心功能。本文将深入探讨如何使用 React Native Testing Library 结合 Mock Service Worker (MSW) 来测试 React Native 应用中涉及网络请求的组件。

为什么需要模拟网络请求

在测试环境中直接发起真实网络请求会带来诸多问题:

  1. 测试结果不可预测,依赖外部服务稳定性
  2. 测试执行速度变慢
  3. 难以模拟各种边界情况(如网络错误、超时等)
  4. 可能产生不必要的测试成本(如API调用次数限制)

实战案例:电话簿应用

我们以一个简单的电话簿应用为例,该应用包含两个主要功能:

  1. 显示所有联系人列表
  2. 显示收藏联系人列表

应用架构分析

应用的主要组件结构如下:

Phonebook.tsx (根组件)
├─ ContactsList.tsx (联系人列表)
├─ FavoritesList.tsx (收藏列表)
└─ api/
   ├─ getAllContacts.ts (获取所有联系人API)
   └─ getAllFavorites.ts (获取收藏联系人API)

核心API调用

应用使用标准的fetch API进行网络请求:

// 获取所有联系人
const res = await fetch('https://randomuser.me/api/?results=25');

// 获取收藏联系人
const res = await fetch('https://randomuser.me/api/?results=10');

测试环境搭建

安装必要依赖

首先需要安装MSW及相关测试依赖:

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

配置MSW服务

在测试文件中,我们需要配置MSW来拦截网络请求:

import { http, HttpResponse } from "msw";
import { setupServer } from "msw/node";

// 1. 定义请求处理器
const handlers = [
  http.get('https://randomuser.me/api/*', () => {
    return HttpResponse.json(MOCK_DATA);
  }),
];

// 2. 创建服务实例
const server = setupServer(...handlers);

// 3. 配置测试生命周期
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());

编写基础测试用例

测试成功场景

it('成功获取联系人并正确渲染列表', async () => {
  render(<PhoneBook />);
  
  // 等待加载状态消失
  await waitForElementToBeRemoved(() => 
    screen.getByText(/users data not quite there yet/i)
  );
  
  // 验证联系人信息是否正确显示
  expect(await screen.findByText('Name: Mrs Ida Kristensen')).toBeOnTheScreen();
  expect(await screen.findByText('Email: ida.kristensen@example.com')).toBeOnTheScreen();
  
  // 验证收藏列表是否正确显示
  expect(await screen.findByText(/my favorites/i)).toBeOnTheScreen();
  expect(await screen.findAllByLabelText('favorite-contact-avatar')).toHaveLength(3);
});

测试失败场景

it('获取联系人失败时显示错误信息', async () => {
  // 模拟API失败
  server.use(
    http.get('https://randomuser.me/api/', ({ request }) => {
      const url = new URL(request.url);
      if (url.searchParams.get('results') === '25') {
        return new HttpResponse(null, { status: 500 });
      }
      return HttpResponse.json(MOCK_DATA);
    })
  );
  
  render(<PhoneBook />);
  
  // 验证错误信息是否正确显示
  expect(await screen.findByText(/an error occurred/i)).toBeOnTheScreen();
});

高级技巧

全局网络请求防护

为了避免测试中遗漏对某些网络请求的模拟,可以将MSW配置移到Jest的全局设置文件中:

// jest-setup.ts
import { server } from './test-utils';

beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());

这样配置后,任何未处理的网络请求都会在控制台显示警告信息。

动态响应模拟

MSW允许我们根据请求参数动态生成响应:

server.use(
  http.get('https://randomuser.me/api/', ({ request }) => {
    const url = new URL(request.url);
    const count = parseInt(url.searchParams.get('results') || '0');
    
    return HttpResponse.json({
      results: Array(count).fill(null).map((_, i) => generateMockUser(i))
    });
  })
);

最佳实践建议

  1. 保持测试独立:每个测试用例后重置MSW处理器
  2. 使用真实数据格式:模拟数据应尽可能接近真实API响应
  3. 覆盖各种场景:包括成功、失败、空数据、加载中等状态
  4. 避免过度模拟:只模拟必要的网络请求
  5. 合理组织测试代码:将常用的模拟数据提取到单独文件中

常见问题解决

测试中出现"unhandled request"警告

这通常意味着:

  1. 测试中发起了未模拟的API请求
  2. 请求URL与模拟的URL不匹配
  3. 请求方法(GET/POST等)不匹配

解决方案:

  1. 检查控制台输出的完整请求URL
  2. 添加对应的请求处理器
  3. 使用通配符(*)匹配URL

异步状态测试技巧

对于涉及网络请求的组件测试:

  1. 使用waitFor处理异步渲染
  2. 使用findBy*查询异步出现的元素
  3. 合理使用act包裹状态更新

总结

通过React Native Testing Library结合MSW,我们可以:

  1. 完全控制测试中的网络行为
  2. 模拟各种网络场景
  3. 编写可靠、快速的网络相关测试
  4. 提前发现潜在的网络请求问题

这种测试方法不仅提高了测试的可靠性,还能帮助开发者更好地理解应用的网络交互行为。