🚀 告别复杂的HTTP模拟!HttpHook让Dart应用测试变得超简单

🚀 告别复杂的HTTP模拟!HttpHook让Dart应用测试变得超简单

在Flutter和Dart开发中,你是否遇到过这些痛点?

  • ❌ 单元测试需要依赖真实的API服务器,导致测试不稳定
  • ❌ 想要模拟各种网络异常情况,但现有工具太复杂
  • ❌ 需要在不同环境间切换API,手动修改代码很麻烦
  • ❌ 想要拦截HTTP请求进行调试,却找不到合适的工具

如果你也有这些困扰,那么HttpHook就是你一直在寻找的解决方案!

🎯 什么是HttpHook?

HttpHook是一个轻量级的Dart HTTP请求拦截与模拟库,专为简化测试和调试而设计。它能让你轻松拦截、模拟和控制应用中的HTTP请求,无需修改业务代码。

核心优势:

  • 🚀 零侵入性 - 无需修改现有HTTP调用代码
  • 🎯 多种匹配模式 - 支持精确URL、路径模板、正则表达式
  • 🔧 灵活的响应控制 - 动态生成响应、模拟延迟和错误
  • 📱 Flutter友好 - 与http包完美集成
  • 🧪 测试利器 - 内置便捷的测试工具函数

🌟 为什么选择HttpHook?

1. 极简的API设计

只需几行代码就能开始使用:

dart 复制代码
import 'package:http_hook/http_hook.dart';

// 一行代码搞定HTTP模拟
mockHttp(
  'http://api.example.com/user/1', 
  reply: '{"id": 1, "name": "张三"}'
);

// 现在所有对这个URL的请求都会返回模拟数据!

2. 强大的路径匹配

告别硬编码URL,支持动态参数:

dart 复制代码
// 🎯 路径模板匹配 - 一个规则匹配所有用户
HttpHook.onTemplate(
  template: '/user/:id',
  method: HttpHookMethod.get,
  respond: (req, match) {
    final userId = match.params!['id']; // 自动提取参数
    return HttpHookResponse.json({
      'id': userId,
      'name': '用户$userId',
      'avatar': 'https://avatar.com/$userId.jpg'
    });
  },
);

// ✅ 匹配:/user/123, /user/456, /user/any-id

3. 通配符域名支持

开发环境、测试环境、生产环境?一套规则搞定所有:

dart 复制代码
// 🌐 匹配任何域名的相同路径
HttpHook.onTemplate(
  template: '/api/login',  // 不指定域名 = 匹配所有域名
  method: HttpHookMethod.post,
  respond: (req, match) => HttpHookResponse.json({
    'token': 'mock-jwt-token',
    'user': {'name': '模拟用户'}
  }),
);

// ✅ 同时匹配:
// - http://dev.api.com/api/login
// - http://test.api.com/api/login  
// - http://prod.api.com/api/login

4. 智能的Pass-Through机制

想要在模拟和真实请求间自由切换?HttpHook让你随心所欲:

dart 复制代码
bool isTestMode = true;

HttpHook.on(
  'http://api.example.com/data',
  method: HttpHookMethod.get,
  respond: (req, match) {
    if (isTestMode) {
      // 测试模式:返回模拟数据
      return HttpHookResponse.json({'mock': '这是测试数据'});
    } else {
      // 生产模式:让请求继续到真实服务器
      return HttpHookResponse.passThrough();
    }
  },
);

🎪 实际应用场景

📱 场景1:Flutter应用单元测试

dart 复制代码
void main() {
  group('用户信息测试', () {
    setUp(() {
      // 模拟用户API
      mockHttp(
        'http://api.app.com/user/profile',
        reply: jsonEncode({
          'name': '李四',
          'email': 'lisi@example.com',
          'level': 'VIP'
        })
      );
    });

    test('应该正确显示用户信息', () async {
      final userService = UserService();
      final profile = await userService.getProfile();
      
      expect(profile.name, '李四');
      expect(profile.level, 'VIP');
    });
  });
}

🔍 场景2:接口调试和错误模拟

dart 复制代码
// 模拟网络超时
HttpHook.on(
  'http://api.example.com/slow-endpoint',
  method: HttpHookMethod.get,
  respond: (req, match) async {
    await Future.delayed(Duration(seconds: 5)); // 模拟慢响应
    return HttpHookResponse.json({'message': '终于返回了'});
  },
);

// 模拟服务器错误
HttpHook.on(
  'http://api.example.com/error-endpoint',
  method: HttpHookMethod.post,
  respond: (req, match) => HttpHookResponse(
    statusCode: 500,
    body: '{"error": "服务器内部错误"}',
  ),
);

🧪 场景3:A/B测试和功能开关

dart 复制代码
final bool enableNewFeature = Random().nextBool();

HttpHook.onRegex(
  regex: RegExp(r'^/api/feature/(.+)$'),
  method: HttpHookMethod.get,
  respond: (req, match) {
    final featureName = match.regexMatch!.group(1);
    
    return HttpHookResponse.json({
      'featureName': featureName,
      'enabled': enableNewFeature,
      'version': enableNewFeature ? 'v2.0' : 'v1.0'
    });
  },
);

🔧 快速上手指南

1. 安装

yaml 复制代码
dev_dependencies:
  http_hook: ^0.0.3

2. 基础使用

dart 复制代码
import 'package:http_hook/http_hook.dart';
import 'package:http/http.dart' as http;

void main() async {
  // 🚀 启动HttpHook
  HttpHook.start();
  
  // 📝 注册一个简单的mock
  HttpHook.on(
    'http://example.com/hello',
    method: HttpHookMethod.get,
    respond: (req, match) => HttpHookResponse.json({
      'message': 'Hello from HttpHook!',
      'timestamp': DateTime.now().toIso8601String()
    }),
  );
  
  // 🌐 发起请求(会被拦截)
  final response = await http.get(Uri.parse('http://example.com/hello'));
  print('响应:${response.body}');
  
  // 🛑 清理资源
  HttpHook.destroy();
}

3. 高级模式

dart 复制代码
// 🎯 使用路径参数
HttpHook.onTemplate(
  template: '/user/:id/posts/:postId',
  method: HttpHookMethod.get,
  respond: (req, match) {
    final userId = match.params!['id'];
    final postId = match.params!['postId'];
    
    return HttpHookResponse.json({
      'userId': userId,
      'postId': postId,
      'title': '用户$userId的第$postId篇文章',
      'content': '这是文章内容...'
    });
  },
);

// 🔄 正则表达式模式
HttpHook.onRegex(
  regex: RegExp(r'^/search\?q=(.+)$'),
  method: HttpHookMethod.get,
  respond: (req, match) {
    final query = match.regexMatch!.group(1);
    return HttpHookResponse.json({
      'query': query,
      'results': ['结果1', '结果2', '结果3'],
      'total': 3
    });
  },
);

🌈 与其他方案的对比

特性 HttpHook dio_interceptor http_mock_adapter
🚀 零侵入性 ❌ 需要修改HTTP客户端 ❌ 需要特殊适配器
🎯 路径模板
🌐 通配符域名
🔄 Pass-through
📱 Flutter兼容
🧪 测试友好 ⚠️

🎉 开始你的HttpHook之旅

还在为HTTP测试和调试烦恼吗?HttpHook让这一切变得简单而优雅。无论你是Flutter新手还是资深开发者,HttpHook都能让你的开发效率翻倍!

GitHub仓库: http_hook 文档: README中文版

💡 小贴士

🔥 最佳实践:

  • 使用mockHttp()进行简单测试,复杂场景使用HttpHook.onXxx()
  • 善用通配符域名匹配,让代码适应多环境
  • 结合Pass-through机制,实现灵活的测试策略

⚠️ 注意事项:

  • 使用HttpHook.onXxx()之类的方法,测试完成后记得调用HttpHook.destroy()清理资源。mockHttp的话则不用(它会自动清理)。
  • 在生产环境中请谨慎使用拦截功能

🌈 一起成长

如果HttpHook帮助到了你,别忘了给我们一个⭐️!有问题或建议?欢迎提issue和PR,让我们一起把HttpHook打造得更好!

让HTTP测试不再是痛点,让开发变得更有趣! 🎉

相关推荐
又见情义5 分钟前
RK3568 Android 13 SDK 开机自动开启共享热点实践
android
mmsx1 小时前
return false 不是拦截:一次按键触发两个动作的事件冒泡陷阱
android·bug
DU_YULIN2 小时前
Camera HAL ThreadManager概述
android·camera hal
淡淡的香烟2 小时前
Android中的MQTT通信原理解析
android·物联网
淡淡的香烟2 小时前
Android Camera开发详解
android·音视频
mmsx3 小时前
基于 Android 的校园信息管理系统源码
android·java·okhttp
xcyxiner4 小时前
flutter wsl2安装记录(使用宿主机虚拟机)
前端·flutter
YF02114 小时前
如何进入Android工程模式
android
Kevin Coding5 小时前
JsonConvert:适用于 Android、鸿蒙与 Flutter 的 JSON 转 Model 插件
android·flutter·harmonyos
xcLeigh7 小时前
Go入门:基本数据类型全览与选择指南
android·服务器·golang·教程·go热门