Flutter测试Mock AuthBloc状态时遇类型不匹配问题求助
问题:Mock Bloc状态时类型不匹配错误
我在测试Widget对Bloc状态变化的响应时,编写了以下测试代码:
class MockAuthBloc extends Mock implements AuthBloc {} void main() { initHydratedStorage(); FlavorConfig( flavor: Flavor.MOCK, baseUrl: 'https://mock.api' ); late MockAuthBloc authBloc; late User user; setUp(() { authBloc = MockAuthBloc(); user = User( email: 'mock@mock.pl', name: 'mock', hasCompletedProfile: true, language: 'pl', id: 1 ); }); testWidgets('navigates to MainNavigator when authenticated', (tester) async { when(() => authBloc.state).thenReturn(AuthState.authenticated(user)); await tester.pumpWidget( MaterialApp( home: BlocProvider<AuthBloc>.value( value: authBloc, child: const LoginPage(), ), ), ); await tester.pumpAndSettle(); expect(find.byType(MainNavigator), findsOneWidget); }); }
执行when(() => authBloc.state).thenReturn(AuthState.authenticated(user));时出现错误:
The argument type 'AuthState' can't be assigned to the parameter type 'AuthState Function()'
我的AuthState类定义如下:
part of 'auth_bloc.dart'; enum AuthStatus { unknown, authenticated, guest, failure, semiAuthenticated} class AuthState { final AuthStatus status; final bool isFirstEntry; final bool isLoadingLong; final String? errorMessage; final String? email; final User? user; const AuthState({ this.status = AuthStatus.unknown, this.isFirstEntry = true, this.isLoadingLong = false, this.errorMessage, this.email, this.user }); const AuthState.unknown() : this(); const AuthState.authenticated(User user) : this( status: AuthStatus.authenticated, user: user, isFirstEntry: false, isLoadingLong: false ); }
尝试其他写法也报错:
写法1:
when(() => authBloc.state).thenReturn(() => AuthState( status: AuthStatus.authenticated, isFirstEntry: false, isLoadingLong: false, user: user ));报错:
Bad state: No method stub was called from withinwhen(). Was a real method called, or perhaps an extension method?写法2:
when(authBloc.state).thenReturn(AuthState( status: AuthStatus.authenticated, isFirstEntry: false, isLoadingLong: false, user: user ));报错:
type 'Null' is not a subtype of type 'AuthState'
解决方法
问题出在Bloc的state是只读getter属性,Mockito对getter的stub方式和普通方法不同:
- 替换
thenReturn为thenAnswer,传入一个返回目标状态的回调函数:
when(() => authBloc.state).thenAnswer((_) => AuthState.authenticated(user));
错误原因解释
- 原写法用
thenReturn直接传入AuthState值,但Mockito在stub getter时,期望接收一个返回该值的函数(AuthState Function()类型),thenAnswer正好用来提供这种回调逻辑。 - 写法1错误:
thenReturn需要传入具体值,而非函数,导致类型不匹配。 - 写法2错误:直接调用
authBloc.state会触发mock的默认getter逻辑(返回null),when无法捕获未执行的表达式,从而抛出类型转换错误。
修正后的完整测试代码:
class MockAuthBloc extends Mock implements AuthBloc {} void main() { initHydratedStorage(); FlavorConfig( flavor: Flavor.MOCK, baseUrl: 'https://mock.api' ); late MockAuthBloc authBloc; late User user; setUp(() { authBloc = MockAuthBloc(); user = User( email: 'mock@mock.pl', name: 'mock', hasCompletedProfile: true, language: 'pl', id: 1 ); }); testWidgets('navigates to MainNavigator when authenticated', (tester) async { // 修正后的stub写法 when(() => authBloc.state).thenAnswer((_) => AuthState.authenticated(user)); await tester.pumpWidget( MaterialApp( home: BlocProvider<AuthBloc>.value( value: authBloc, child: const LoginPage(), ), ), ); await tester.pumpAndSettle(); expect(find.byType(MainNavigator), findsOneWidget); }); }
内容的提问来源于stack exchange,提问作者Karol Wiśniewski
相关产品推荐
相关产品推荐

