🚀 告别复杂的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测试不再是痛点,让开发变得更有趣! 🎉

相关推荐
zepcjsj08012 小时前
简单实现支付密码的页面及输入效果
android
小阳睡不醒3 小时前
小白成长之路-部署Zabbix7(二)
android·运维
mmoyula4 小时前
【RK3568 PWM 子系统(SG90)驱动开发详解】
android·linux·驱动开发
ITfeib6 小时前
Flutter基础
flutter
你过来啊你7 小时前
Android用户鉴权实现方案深度分析
android·鉴权
RaidenLiu9 小时前
RepaintBoundary是什么?怎么用?
flutter
kerli9 小时前
Android 嵌套滑动设计思想
android·客户端
恣艺10 小时前
LeetCode 854:相似度为 K 的字符串
android·算法·leetcode
阿华的代码王国11 小时前
【Android】相对布局应用-登录界面
android·xml·java