Dart单元测试报错:预期Future<SignUpResultSuccess>实际为Future<SignUpResult>
问题原因
- 业务代码中
AuthenticationRepository的signUp方法显式声明返回类型为Future<SignUpResult>,即便运行时实际返回的是SignUpResultSuccess或SignUpResultFailure子类实例,方法的静态返回类型依然是父类SignUpResult,直接对比两个Future实例时,泛型静态类型不匹配就会触发你遇到的报错。 - 测试代码没有正确处理异步逻辑:未将测试函数标记为
async,也没有等待异步方法执行完成就直接对比Future实例本身,不符合Flutter异步单元测试的规范。
你当前的业务代码定义是合理的,不需要修改,只要调整测试的断言逻辑即可。
解决方案
有两种常用的修改方案:
方案1:await异步结果后匹配实例值
由于你的SignUpResult子类都继承了Equatable,实例可直接比较值,修改后的测试代码如下:
import 'package:flutter_test/flutter_test.dart'; import 'package:mocktail/mocktail.dart'; import 'package:pocket_open_access/app/features/authentication/data/authentication_data_provider.dart'; import 'package:pocket_open_access/app/features/authentication/repository/authentication_repository.dart'; class MockAuthenticationDataProvider extends Mock implements AuthenticationDataProvider {} void main() { late AuthenticationRepository authenticationRepository; late AuthenticationDataProvider mockAuthenticationDataProvider; const String email = 'test@test.com'; const String password = '1234567'; setUp( () { mockAuthenticationDataProvider = MockAuthenticationDataProvider(); authenticationRepository = AuthenticationRepository( authenticationDataProvider: mockAuthenticationDataProvider, ); }, ); group( 'Sign-up user:', () { test( 'is successful so returns SignUpResultSuccess()', // 测试函数标记为async () async { when(() => mockAuthenticationDataProvider.createEmailAccount( email: any(named: 'email'), password: any(named: 'password'), )).thenAnswer( (_) async {}, ); // 等待异步方法执行完成拿到结果 final result = await authenticationRepository.signUp(email: email, password: password); // 直接匹配结果值 expect(result, const SignUpResultSuccess()); }, ); test( 'fails so returns SignUpResultFailure with error code', // 测试函数标记为async () async { when( () => mockAuthenticationDataProvider.createEmailAccount( email: any(named: 'email'), password: any(named: 'password'), ), ).thenThrow(CreateEmailAccountException(errorCode: 'error-code')); // 等待异步方法执行完成拿到结果 final result = await authenticationRepository.signUp(email: email, password: password); // 直接匹配结果值 expect(result, const SignUpResultFailure(errorCode: 'error-code')); }, ); }, ); }
方案2:用类型匹配器验证返回类型
如果你只需要验证返回结果的类型,不需要精确匹配字段值,可以用isA匹配器:
// 成功场景验证类型 expect(result, isA<SignUpResultSuccess>()); // 失败场景验证类型+字段 expect(result, isA<SignUpResultFailure>()); expect((result as SignUpResultFailure).errorCode, 'error-code');
内容的提问来源于stack exchange,提问作者Luke
相关产品推荐
相关产品推荐

