使用Mocktail测试Flutter ApiProvider报Null不是Future<Response>子类型错误
问题根因
- HTTP请求Mock不完整:你在测试中对
httpClient.post的Mock只匹配了第一个位置参数Uri,但是业务代码中调用post方法时还传入了body命名参数,Mocktail无法匹配到符合完整参数的Stub,因此返回Null,触发Null不是Future<Response>类型错误。 - 异常测试写法错误:你直接
await调用会抛出异常的login方法,还没执行到expect断言就会触发运行时错误,不符合异步异常测试的写法要求。 - 多余的被测类Mock:你后续添加的对
apiProvider.login本身的Mock完全错误,单元测试中被测类的逻辑需要真实执行,只需要Mock它的外部依赖(也就是httpClient),对被测类自身方法Mock会导致真实逻辑无法运行,同时返回的String类型和post方法需要的Response类型不匹配,触发第二个类型错误。
修复方案
修改测试代码中login分组的测试逻辑,补全Mock的参数匹配,调整异常测试写法,删除多余的被测类Mock即可:
group('login', () { test('Throws Exception on non-200 response', () async { final response = MockResponse(); when(() => response.statusCode).thenReturn(400); when(() => response.body).thenReturn(''); // 补全post方法的参数匹配,包含body命名参数 when(() => httpClient.post(any(), body: any(named: 'body'))) .thenAnswer((_) async => response); // 不要提前await,使用expectLater配合异步异常匹配 await expectLater(apiProvider.login(const User.empty()), throwsA(isA<Exception>())); }); });
如果需要更严格的参数校验,也可以将any(named: 'body')替换为实际传入的参数{"username": "", "password": ""},实现对请求参数的精准验证。
内容的提问来源于stack exchange,提问作者Brenno Barbosa
相关产品推荐
相关产品推荐

