Flutter单元测试:如何正确Mock GoogleSignIn并解决断言错误?
Flutter单元测试Google登录:解决'accessToken != null || idToken != null'断言错误
问题核心
这个断言错误是因为GoogleAuthProvider.credential()要求必须传入idToken或accessToken中的至少一个,你的Mock类没有正确返回这两个值,导致调用credential方法时参数全为空。
正确的Mock类实现
1. 修复MockGoogleSignInAuthentication
需要明确给idToken或accessToken赋值(二选一即可):
class MockGoogleSignInAuthentication extends Mock implements GoogleSignInAuthentication { // 固定返回一个模拟的ID令牌,也可以换成accessToken @override String? get idToken => 'mock-google-id-token'; @override String? get accessToken => null; }
2. 确保MockGoogleSignInAccount返回有效Authentication
让模拟的Google登录账号返回上面的Authentication实例:
class MockGoogleSignInAccount extends Mock implements GoogleSignInAccount { @override Future<GoogleSignInAuthentication> get authentication async => MockGoogleSignInAuthentication(); }
3. 让MockGoogleSignIn返回有效账号
确保模拟的GoogleSignIn类调用signIn()时返回上面的账号实例:
class MockGoogleSignIn extends Mock implements GoogleSignIn { @override Future<GoogleSignInAccount?> signIn() async => MockGoogleSignInAccount(); // 如果业务代码用到静默登录,也要同步设置 @override Future<GoogleSignInAccount?> signInSilently() async => MockGoogleSignInAccount(); }
测试代码调整
在测试用例中正确绑定Mock行为,并模拟Firebase的登录逻辑:
void main() { late MockFirebaseAuth mockFirebaseAuth; late MockGoogleSignIn mockGoogleSignIn; setUp(() { mockFirebaseAuth = MockFirebaseAuth(); mockGoogleSignIn = MockGoogleSignIn(); // 绑定GoogleSignIn的signIn行为 when(mockGoogleSignIn.signIn()).thenAnswer((_) async => MockGoogleSignInAccount()); // 模拟Firebase用Google凭证登录成功的场景 final mockCredential = GoogleAuthProvider.credential(idToken: 'mock-google-id-token'); when(mockFirebaseAuth.signInWithCredential(mockCredential)) .thenAnswer((_) async => UserCredential(user: MockUser())); }); test('Google登录流程测试', () async { // 注入Mock实例到业务类 final authService = AuthService( firebaseAuth: mockFirebaseAuth, googleSignIn: mockGoogleSignIn, ); // 执行登录方法 final result = await authService.signInWithGoogle(); // 断言验证 expect(result, isNotNull); verify(mockGoogleSignIn.signIn()).called(1); verify(mockFirebaseAuth.signInWithCredential(any)).called(1); }); }
业务代码验证
确保业务代码中正确从GoogleSignInAccount获取Authentication并传入credential:
class AuthService { final FirebaseAuth _firebaseAuth; final GoogleSignIn _googleSignIn; AuthService({FirebaseAuth? firebaseAuth, GoogleSignIn? googleSignIn}) : _firebaseAuth = firebaseAuth ?? FirebaseAuth.instance, _googleSignIn = googleSignIn ?? GoogleSignIn(); Future<UserCredential?> signInWithGoogle() async { try { final googleUser = await _googleSignIn.signIn(); if (googleUser == null) return null; final googleAuth = await googleUser.authentication; final credential = GoogleAuthProvider.credential( idToken: googleAuth.idToken, accessToken: googleAuth.accessToken, ); return await _firebaseAuth.signInWithCredential(credential); } catch (e) { return null; } } }
常见坑点排查
- 不要将MockGoogleSignInAuthentication的
idToken和accessToken同时设为null - 必须确保MockGoogleSignInAccount的
authenticationgetter返回有效实例,不能留空 - 测试前要通过
when()正确绑定Mock类的行为,避免默认返回null
内容的提问来源于stack exchange,提问作者Yura
相关产品推荐
相关产品推荐

