Flutter自定义页面Widget测试触发HttpClient警告如何解决?
错误原因
Flutter Widget测试默认会拦截所有HTTP请求,不允许真实网络请求发出,你的代码里有两个场景会触发HTTP请求导致告警:
- 老师头像存在网络地址时,
NetworkImage组件会发起请求加载图片 - 页面
build方法中Future.wait依赖的_teacherData、_campusData等异步接口底层使用了HttpClient发起网络请求
解决步骤
1. 模拟页面异步数据源
不要让页面在测试中发起真实接口请求,直接返回预设的测试数据,可根据你的情况二选一:
- 优先方案:调整页面代码,把四个异步请求的依赖改成可注入参数,测试时直接传入写死的mock数据即可,不需要修改业务逻辑
- 兼容方案:如果不想改动现有页面代码,可使用mock工具拦截对应接口的调用,返回预设的测试数据,包含你要验证的老师姓名、校区地址等字段即可。
2. 处理NetworkImage的请求
有两种方案避免头像加载触发网络请求:
- 测试时给
teacherData['user']['img_url']传空值,让页面自动走本地占位图逻辑,不会触发网络请求 - 如果需要测试头像正常加载的场景,可使用
HttpOverrides全局拦截测试中的图片请求,返回模拟响应,示例代码如下:
import 'dart:io'; import 'package:flutter_test/flutter_test.dart'; void main() { setUp(() { // 全局拦截所有HTTP请求 HttpOverrides.global = _MockHttpOverrides(); }); // 这里写你的测试用例 } class _MockHttpOverrides extends HttpOverrides { @override HttpClient createHttpClient(SecurityContext? context) { return super.createHttpClient(context) ..getUrl = (Uri uri) async => _MockHttpClientRequest() ..get = (uri, path) async => _MockHttpClientRequest(); } } class _MockHttpClientRequest extends Fake implements HttpClientRequest { @override Future<HttpClientResponse> close() async => _MockHttpClientResponse(); } class _MockHttpClientResponse extends Fake implements HttpClientResponse { @override int get statusCode => HttpStatus.ok; @override Stream<List<int>> get body => Stream.value(<int>[]); @override int get contentLength => 0; @override HttpHeaders get headers => HttpHeaders(); }
3. 基础测试用例示例
测试Text组件是否正常显示的参考代码如下:
import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; // 导入你的BookingDetails页面 import 'package:your_app/booking_details.dart'; void main() { setUp(() { HttpOverrides.global = _MockHttpOverrides(); }); testWidgets('验证BookingDetails页面文本显示正常', (tester) async { // 构造测试需要的mock数据 final mockBooking = {'cancelled_by_inst': false, 'teacher_id': '1001'}; final mockTeacherData = { 'user': { 'first_name': '李', 'last_name': '明', 'img_url': '' } }; final mockCampusData = [ {'address_line1': '学院路15号', 'suburb': '海淀区', 'state': '北京', 'postcode': '100083'} ]; // 加载页面,必须套MaterialApp提供必要的主题、路由等依赖 await tester.pumpWidget( MaterialApp( home: BookingDetails(mockBooking), ), ); // 等待Future加载完成、页面渲染结束 await tester.pumpAndSettle(); // 验证目标Text组件是否存在 expect(find.text('李'), findsOneWidget); expect(find.text('明'), findsOneWidget); expect(find.text('学院路15号, 海淀区, 北京 100083 '), findsOneWidget); }); } // 上面的_MockHttpOverrides类写在这里即可
内容的提问来源于stack exchange,提问作者Gurjit Singh
相关产品推荐
相关产品推荐

