I have a MyBloc bloc that accepts an event MyEventActivate. This event fails when MyBloc.state is not MyStateSuccess.
// * my_bloc.dart
/// mapEventToState for [MyEventActivate].
Stream<MyState> _activate() async* {
if (state is MyStateSuccess) {
yield MyStateParsedSuccess(state.data);
} else {
yield MyStateError('Cannot activate: wrong state $state');
}
}
I want to test the functionality of MyEventActivate with something like this:
// * my_bloc_test.dart
blocTest(
'Emits [MyStateParsedSuccess] when MyEventActivate is called & current state is MyStateSuccess',
build: () async {
final MyStateSuccess startState = MyStateSuccess(data: 'mock success');
// TODO: somehow initialize bloc.state to `startState` here
return bloc;
},
act: (MyBloc bloc) async => bloc.add(MyEventActivate()),
expect: [MyStateParsedSuccess('mock success')],
);
Is it possible to initialize MyBloc with a specific state startState during BlocTest.build? I have tried using BlocTest.skip which works OK, but then I still need to somehow run some business logic to end up at startState.
Hi @sterrenburg 馃憢
Thanks for opening an issue!
You can run whatever setup code you need in the build of blocTest and use skip to only assert for the state(s) after the setup.
blocTest(
'emits 2 when CounterEvent.increment is added',
build: () async => CounterBloc()..add(CounterEvent.increment),
act: (bloc) => bloc.add(CounterEvent.increment),
skip: 2,
expect: [2],
);
Hope that helps 馃憤
Thank you for your answer!
That works as expected, and is how I am testing the event right now. The issue to me is that this approach requires some implementation for handling CounterEvent.increment, which is outside the responsibility of _activate.
In this example, I would like to start off with a MyBloc with some particular state that is not MyInitialState. That way, the test does not depend on the functionality that produces the particular state. Does that make sense, or am I approaching the modularity of the test in a wrong manner?
@sterrenburg I think the key thing to note is you're testing the real bloc so you only have access to the API of the real bloc. There is no magic way to initialize a bloc with a given state in a test and I would encourage you to think of each test as exercising a sequence of one or more events. You always need to start at the initialState but certain tests can add more events and build on functionality from previous tests. Hope that helps 馃憤
That makes sense, your example is definitely the best example then. Thank you for making blocs easy to test!
Most helpful comment
That makes sense, your example is definitely the best example then. Thank you for making blocs easy to test!