26
loading...
This website collects cookies to deliver better user experience
blocTest
does seem to have an option to skip a number of previously emitted values and to seed the current state and start from there. But this is a bit annoying in my opinion since you might not now how many emissions have been sent for a particular state to be reachedmatchers
package to do more flexible assertions, but to my surprise matchers didn't play around very nicely with blocTest
function (I might be missing something, leave a comment if you know a workaround)blocTest
you have to explicitly say what previous states have been (or skip them).blocTest(
'emits [-1] when CounterEvent.decrement is added',
build: () => counterBloc,
act: (bloc) => bloc.add(CounterEvent.decrement),
expect: () => [-1], // the history of all emitted states up until now :(
);
expect
parameter but did not work.cubitTest('Emits loaded state when registration service succeeds',
build: () => sut,
stateField: (RegistrationState state) => state.status,
arrange: () {
when(
() => mockRegistrationService.register(
email: any(named: 'email'), password: any(named: 'password')),
).thenAnswer((_) async {
return;
});
sut.updateEmail('[email protected]');
sut.updatePassword('12345678');
},
act: (RegistrationCubit cubit) => cubit.register(),
assertions: (MockCallable<Status> updatesStatusWith) {
verify(() => updatesStatusWith(Status.loaded));
});
verify(() => updatesStatusWith(Status.loaded)),
// OR
verifyInOrder([
() => updatesStatusWith(Status.loading),
() => updatesStatusWith(Status.loaded),
]);
Note in this example I'm using mocktail
instead of mockito
but either could be used. Same goes for cubit or bloc
blocTest
this also gives the same feel for arrange, act, assert structure but with some key differences, here is a short explanation of critical parameters:stateField
is interesting because it allows selecting a the particular state property you're interested in.
assertions
is a closure with a single parameter of type MockCallable where T will be whatever you selected with stateField
Note that stateField could be the identity function in which case you could do assertions over the entire state
build
should return new instances of the bloc or cubit but I actually reuse the same instance for all tests so I can use the setup method and benefit from that as well. abstract class Callable<T> {
void call([T? arg]) {}
}
class MockCallable<T> extends Mock implements Callable<T> {}
@isTest
void cubitTest<P, S, B extends BlocBase<S>>(
String description, {
required B Function() build,
required FutureOr Function(B) act,
required P Function(S) stateField,
Function? arrange,
Function(P)? inspect,
required void Function(MockCallable<P> updatesWith) assertions,
}) async {
test(description, () async {
final expectation = MockCallable<P>();
arrange?.call();
final bloc = build();
bloc.stream.listen((S state) {
final focusedProperty = stateField(state);
inspect?.call(focusedProperty);
expectation(focusedProperty);
});
await act(bloc);
await bloc.close();
assertions(expectation);
});
}