I am having this code where I am listening to two states in the BlocListener:
https://github.com/mihai9112/reazzon/blob/feature/testing/lib/src/pages/login_page.dart#L55
According to a question I raised on StackOverflow, one test is failing (the second state listened) with the assertion failing to find the widget in question.
Is this a limitation of the BlocListener? Or am I missing something?
Hi @mihai9112 馃憢
Thanks for opening an issue!
The problem you're running into is a timing issue. When you use whenListen it immediately seeds the bloc with that stream of states so when BlocListener subscribes it will begin reacting right away.
If you simply want to test the SnackBar functionality I would recommend refactoring your tests like:
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:reazzon/src/login/login_bloc.dart';
import 'package:reazzon/src/login/login_state.dart';
import 'package:reazzon/src/pages/login_page.dart';
import 'package:bloc_test/bloc_test.dart';
import '../authentication_tests/authentication_mock.dart';
void main() async {
AuthenticationRepositoryMock _authenticationRepositoryMock;
LoginBlocMock _loginBloc;
final snackBarFailureFinder = find.byKey(Key("snack_bar_failure"));
final snackBarLoadingFinder = find.byKey(Key("snack_bar_loading"));
Widget makeTestableWidget() {
return BlocProvider<LoginBloc>(
builder: (context) => _loginBloc,
child: MaterialApp(
home: Scaffold(
body: LoginPage(),
)),
);
}
setUp(() {
_authenticationRepositoryMock = AuthenticationRepositoryMock();
_loginBloc =
LoginBlocMock(authenticationRepository: _authenticationRepositoryMock);
});
testWidgets('Show snack bar when state is LoginFailure',
(WidgetTester tester) async {
//Arrange
final expectedStates = [
LoginInitial(),
LoginFailure(
error: "Could not find user. Please try different credentials")
];
whenListen(_loginBloc, Stream.fromIterable(expectedStates));
//Act
await tester.pumpWidget(makeTestableWidget());
expect(snackBarFailureFinder, findsNothing);
await tester.pump();
//Assert
expect(snackBarFailureFinder, findsOneWidget);
});
testWidgets('Show snack bar when state is LoginLoading',
(WidgetTester tester) async {
//Arrange
final expectedStates = [LoginInitial(), LoginLoading()];
whenListen(_loginBloc, Stream.fromIterable(expectedStates));
//Act
await tester.pumpWidget(makeTestableWidget());
expect(snackBarLoadingFinder, findsNothing);
await tester.pump();
//Assert
expect(snackBarLoadingFinder, findsOneWidget);
});
}
Hope that helps 馃憤
Most helpful comment
Hi @mihai9112 馃憢
Thanks for opening an issue!
The problem you're running into is a timing issue. When you use
whenListenit immediately seeds the bloc with that stream of states so whenBlocListenersubscribes it will begin reacting right away.If you simply want to test the
SnackBarfunctionality I would recommend refactoring your tests like:Hope that helps 馃憤