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