如何使用http_mock_adapter验证已发起的Dio HTTP请求?
使用http_mock_adapter验证请求发起的解决方案
你不需要mock上层调用类,http_mock_adapter本身内置了请求记录能力,可直接用来做验证,是最优解。
方案1:使用内置history属性(优先推荐)
DioAdapter实例会自动存储所有经过它的请求记录,直接读取history属性即可断言请求是否发起、参数是否正确,示例代码如下:
import 'package:dio/dio.dart'; import 'package:http_mock_adapter/http_mock_adapter.dart'; import 'package:test/test.dart'; void main() { late Dio dio; late DioAdapter mockAdapter; setUp(() { dio = Dio(); mockAdapter = DioAdapter(dio: dio); dio.httpClientAdapter = mockAdapter; // 预先设置模拟响应 mockAdapter.onGet( '/user', (server) => server.reply(200, {'id': 1, 'name': 'test'}), queryParameters: {'id': '1'}, ); }); test('验证指定GET请求成功发起', () async { // 执行业务代码触发请求 await dio.get('/user', queryParameters: {'id': '1'}); // 断言请求记录 // 1. 验证总请求数 expect(mockAdapter.history.length, 1); // 2. 验证请求方法、路径、参数 final targetRequest = mockAdapter.history.first; expect(targetRequest.method, 'GET'); expect(targetRequest.path, '/user'); expect(targetRequest.queryParameters, {'id': '1'}); // 也可验证请求头、请求体等其他属性 }); }
你还可以自定义匹配规则做更灵活的验证:
- 验证指定路径的POST请求恰好发起2次:
final postRequests = mockAdapter.history.where( (req) => req.method == 'POST' && req.path == '/submit' ); expect(postRequests, hasLength(2)); - 验证从未发起过到
/delete路径的请求:final deleteRequests = mockAdapter.history.where((req) => req.path == '/delete'); expect(deleteRequests, isEmpty);
方案2:自定义拦截器记录请求(可选)
如果你有特殊的统计需求,也可以给Dio实例添加自定义拦截器自行记录请求:
class RequestRecordInterceptor extends Interceptor { List<RequestOptions> recordedRequests = []; @override void onRequest(RequestOptions options, RequestInterceptorHandler handler) { recordedRequests.add(options); super.onRequest(options, handler); } } // 使用时添加到dio实例 final recordInterceptor = RequestRecordInterceptor(); dio.interceptors.add(recordInterceptor); // 验证时直接访问recordInterceptor.recordedRequests做断言
上述两种方案都不需要额外维护上层调用类的桩代码,远优于你提到的mock上层类的方案,优先使用方案1即可。
内容的提问来源于stack exchange,提问作者Hannes Hultergård
相关产品推荐
相关产品推荐

