Flutter单元测试Mock Http请求报错:Null无法转为Future<Response<dynamic>>
解决Mockito单元测试报错
type 'Null' is not a subtype of type 'Future<Response<dynamic>>' 核心问题分析
报错的直接原因是Mockito的mock匹配失败,导致mockApiConnect.get()返回null,而非预期的Future<Response>。同时HomeProvider.getUser()的异步逻辑也存在问题,即便mock正常工作,也会返回空列表。
问题1:Mock的URL参数不匹配
HomeProvider.getUser()中调用的是api.get(EndPoints.user, ...),但测试代码里写的是:
when(mockApiConnect.get(EndPoints.baseUrl, headers: {"app-id": "myAppID"}))
URL参数不一致,Mockito无法匹配到对应的mock方法,因此返回null。
问题2:HomeProvider.getUser()异步逻辑错误
使用.then()处理Future但未等待其完成就直接返回空列表user,导致测试拿到的是未填充数据的空列表,同时会隐藏潜在错误。
问题3:泛型方法的Mock匹配(可选但重要)
ApiConnect.get()是泛型方法,Mockito处理泛型时需明确类型,否则可能出现匹配问题。
修复步骤
1. 修正Mock的URL参数
将测试中的EndPoints.baseUrl改为EndPoints.user,与实际调用保持一致:
when(mockApiConnect.get(EndPoints.user, headers: {"app-id": "myAppID"})) .thenAnswer((_) async => Response(body: response, statusCode: 200));
2. 修复HomeProvider.getUser()的异步逻辑
改用await等待API请求完成后再返回数据,同时优化错误处理:
Future<List<User>> getUser() async { try { final response = await api.get(EndPoints.user, headers: {"app-id": "myAppID"}); return (response.body['data'] as List).map((value) => User.fromJson(value)).toList(); } catch (error) { print(error.toString()); return []; // 也可抛出错误交由上层处理 } }
3. 优化泛型方法的Mock(可选)
若仍存在泛型匹配问题,可明确指定泛型类型或使用any匹配参数:
// 方式1:明确泛型类型 when(mockApiConnect.get<dynamic>(EndPoints.user, headers: {"app-id": "myAppID"})) .thenAnswer((_) async => Response(body: response, statusCode: 200)); // 方式2:使用any匹配参数(参数不确定时) when(mockApiConnect.get(any, headers: anyNamed('headers'))) .thenAnswer((_) async => Response(body: response, statusCode: 200));
完整修复后的测试代码
import 'package:flutter_test/flutter_test.dart'; import 'package:get/get_connect/http/src/response/response.dart'; import 'package:mockito/mockito.dart'; import 'package:trial/app/data/api/api_connect.dart'; import 'package:trial/app/data/model/user.dart'; import 'package:trial/app/data/provider/home_provider.dart'; import 'package:trial/app/utils/constants.dart'; class MockApiConnect extends Mock implements ApiConnect {} void main() { group('HomeProvider', () { late HomeProvider homeProvider; late MockApiConnect mockApiConnect; setUp(() { mockApiConnect = MockApiConnect(); homeProvider = HomeProvider(); homeProvider.api = mockApiConnect; }); test('getUser returns list of users on success', () async { // arrange final response = { 'data': [ {'id': 1, 'firstName': 'John Doe'}, {'id': 2, 'firstName': 'Jane Doe'} ] }; when(mockApiConnect.get<dynamic>(EndPoints.user, headers: {"app-id": "myAppID"})) .thenAnswer((_) async => Response(body: response, statusCode: 200)); // act final result = await homeProvider.getUser(); // assert expect(result, isA<List<User>>()); expect(result.length, 2); expect(result[0].id, 1); expect(result[0].firstName, 'John Doe'); expect(result[1].id, 2); expect(result[1].firstName, 'Jane Doe'); }); }); }
内容的提问来源于stack exchange,提问作者Mistuu
相关产品推荐
相关产品推荐

