Flutter单元测试报错:Expected<false> Actual<Closure: ()=>Future<bool>>如何修复?
问题背景
我正在为AuthService类中的authorize异步方法编写单元测试,该方法代码如下:
Future<bool> authorize() async { AuthorizationTokenResponse? authResult; try { authResult = await appAuth.authorizeAndExchangeCode( AuthorizationTokenRequest( bsEnv.AD_CLIENT_ID!, )); if (authResult != null) { return true; } } on PlatformException catch (e) { forgetPassword(); } } return false; }
使用Mocktail创建Mock对象编写的测试代码如下:
class MockBEnv extends Mock implements BEnv {} class MockSharedPrefsService extends Mock implements SharedPrefsService {} class MockFlutterAppAuth extends Mock implements FlutterAppAuth {} class MockAuthorizationServiceConfiguration extends Mock implements AuthorizationServiceConfiguration {} class MockAuthorizationTokenResponse extends Mock implements AuthorizationTokenResponse {} class MockAuthorizationTokenRequest extends Mock implements AuthorizationTokenRequest {} class MockTokenResponse extends Mock implements TokenResponse{} class MockTokenRequest extends Mock implements TokenRequest{ } void main() { late AuthService authService; late MockFlutterAppAuth mockFlutterAppAuth; late MockBEnv mockBEnv; late MockSharedPrefsService mockStorageService; late MockAuthorizationTokenResponse mockAuthorizationTokenResponse; late MockAuthorizationTokenRequest mockAuthorizationTokenRequest; const tUrl = 'https://endpoint/'; const tUserImp = 'user'; const tAppLan = 'sv-SE'; const tClientId = 'client'; const tIosUri = 'ios'; const tTokenEndPoint = 'abcdeff'; setUp(() { mockFlutterAppAuth = MockFlutterAppAuth(); mockBEnv = MockBEnv(); mockStorageService = MockSharedPrefsService(); mockAuthorizationTokenRequest = MockAuthorizationTokenRequest(); mockAuthorizationTokenResponse = MockAuthorizationTokenResponse(); authService = AuthService( appAuth: mockFlutterAppAuth, bsEnv: mockBEnv, sharedPrefs: mockStorageService); }); group('authorize', () { test( 'should return true when the call to authorized method if result is not null', () async { // Arrange when(() => mockBEnv.AD_CLIENT_ID).thenAnswer((_) => tClientId); when(() => mockFlutterAppAuth .authorizeAndExchangeCode(mockAuthorizationTokenRequest)) .thenAnswer((_)=> Future.value(mockAuthorizationTokenResponse)); // Act final result = authService.authorize; // Assert expect(() => result(), equals(false)); }); }); }
执行测试时出现错误:Expected: <false>,Actual: <Closure: () => Future<bool>>
错误原因与修复步骤
1. 未正确调用异步方法
原测试中final result = authService.authorize;只是获取了方法的引用,没有执行该方法,且异步方法必须通过await来获取最终的布尔结果。
2. Mock请求对象不匹配
原测试中Mock的是mockAuthorizationTokenRequest实例,但实际代码里是新建了一个AuthorizationTokenRequest对象,Mocktail默认采用严格匹配,导致Mock的方法不会被触发。
3. 断言逻辑与测试预期矛盾
测试用例描述是“当授权调用返回非null结果时返回true”,但断言却期望返回false,逻辑完全相反。
修复后的测试代码
group('authorize', () { test('should return true when authorization call returns non-null result', () async { // Arrange when(() => mockBEnv.AD_CLIENT_ID).thenReturn(tClientId); // 用any()匹配任意AuthorizationTokenRequest实例,也可以用argThat做精确匹配 when(() => mockFlutterAppAuth.authorizeAndExchangeCode(any())) .thenAnswer((_) => Future.value(mockAuthorizationTokenResponse)); // Act final result = await authService.authorize(); // 调用方法并await获取异步结果 // Assert expect(result, equals(true)); // 匹配测试预期的true // 验证Mock方法确实被调用过一次 verify(() => mockFlutterAppAuth.authorizeAndExchangeCode(any())).called(1); }); });
可选:精确匹配请求对象
如果需要验证传入的AuthorizationTokenRequest的属性是否正确,可以用argThat做精确匹配:
when(() => mockFlutterAppAuth.authorizeAndExchangeCode( argThat((request) => request.clientId == tClientId) )).thenAnswer((_) => Future.value(mockAuthorizationTokenResponse));
内容的提问来源于stack exchange,提问作者Shashiwadana
相关产品推荐
相关产品推荐

