11@Timeout (Duration (milliseconds: 500 ))
2+ import 'package:ecommerce_app/src/features/authentication/data/fake_auth_repository.dart' ;
23import 'package:ecommerce_app/src/features/authentication/presentation/account/account_screen_controller.dart' ;
34import 'package:flutter_riverpod/flutter_riverpod.dart' ;
45import 'package:flutter_test/flutter_test.dart' ;
@@ -7,56 +8,112 @@ import 'package:mocktail/mocktail.dart';
78import '../../../../mocks.dart' ;
89
910void main () {
10- late MockAuthRepository authRepository;
11- late AccountScreenController controller;
12- setUp (() {
13- authRepository = MockAuthRepository ();
14- controller = AccountScreenController (
15- authRepository: authRepository,
11+ ProviderContainer makeProviderContainer (MockAuthRepository authRepository) {
12+ final container = ProviderContainer (
13+ overrides: [
14+ authRepositoryProvider.overrideWithValue (authRepository),
15+ ],
1616 );
17+ addTearDown (container.dispose);
18+ return container;
19+ }
20+
21+ setUpAll (() {
22+ registerFallbackValue (const AsyncLoading <int >());
1723 });
24+
1825 group ('AccountScreenController' , () {
19- test ('initial state is AsyncValue.data' , () {
26+ test ('initial state is AsyncData' , () {
27+ final authRepository = MockAuthRepository ();
28+ // create the ProviderContainer with the mock auth repository
29+ final container = makeProviderContainer (authRepository);
30+ // create a listener
31+ final listener = Listener <AsyncValue <void >>();
32+ // listen to the provider and call [listener] whenever its value changes
33+ container.listen (
34+ accountScreenControllerProvider,
35+ listener.call,
36+ fireImmediately: true ,
37+ );
38+ // verify
39+ verify (
40+ // the build method returns a value immediately, so we expect AsyncData
41+ () => listener (null , const AsyncData <void >(null )),
42+ );
43+ // verify that the listener is no longer called
44+ verifyNoMoreInteractions (listener);
45+ // verify that [signInAnonymously] was not called during initialization
2046 verifyNever (authRepository.signOut);
21- expect (controller.state, const AsyncData <void >(null ));
2247 });
2348
2449 test ('signOut success' , () async {
2550 // setup
26- when (authRepository.signOut).thenAnswer (
27- (_) => Future .value (),
28- );
29- // expect later
30- expectLater (
31- controller.stream,
32- emitsInOrder (const [
33- AsyncLoading <void >(),
34- AsyncData <void >(null ),
35- ]),
51+ final authRepository = MockAuthRepository ();
52+ // stub method to return success
53+ when (authRepository.signOut).thenAnswer ((_) => Future .value ());
54+ // create the ProviderContainer with the mock auth repository
55+ final container = makeProviderContainer (authRepository);
56+ // create a listener
57+ final listener = Listener <AsyncValue <void >>();
58+ // listen to the provider and call [listener] whenever its value changes
59+ container.listen (
60+ accountScreenControllerProvider,
61+ listener.call,
62+ fireImmediately: true ,
3663 );
64+ // sto
65+ const data = AsyncData <void >(null );
66+ // verify initial value from build method
67+ verify (() => listener (null , data));
3768 // run
69+ final controller =
70+ container.read (accountScreenControllerProvider.notifier);
3871 await controller.signOut ();
3972 // verify
73+ verifyInOrder ([
74+ // set loading state
75+ // * use a matcher since AsyncLoading != AsyncLoading with data
76+ // * https://codewithandrea.com/articles/unit-test-async-notifier-riverpod/
77+ () => listener (data, any (that: isA <AsyncLoading >())),
78+ // data when complete
79+ () => listener (any (that: isA <AsyncLoading >()), data),
80+ ]);
81+ verifyNoMoreInteractions (listener);
4082 verify (authRepository.signOut).called (1 );
4183 });
4284 test ('signOut failure' , () async {
4385 // setup
86+ final authRepository = MockAuthRepository ();
87+ // stub method to return success
4488 final exception = Exception ('Connection failed' );
4589 when (authRepository.signOut).thenThrow (exception);
46- // expect later
47- expectLater (
48- controller.stream,
49- emitsInOrder ([
50- const AsyncLoading <void >(),
51- predicate <AsyncValue <void >>((value) {
52- expect (value.hasError, true );
53- return true ;
54- }),
55- ]),
90+ // create the ProviderContainer with the mock auth repository
91+ final container = makeProviderContainer (authRepository);
92+ // create a listener
93+ final listener = Listener <AsyncValue <void >>();
94+ // listen to the provider and call [listener] whenever its value changes
95+ container.listen (
96+ accountScreenControllerProvider,
97+ listener.call,
98+ fireImmediately: true ,
5699 );
100+ const data = AsyncData <void >(null );
101+ // verify initial value from build method
102+ verify (() => listener (null , data));
57103 // run
104+ final controller =
105+ container.read (accountScreenControllerProvider.notifier);
58106 await controller.signOut ();
59107 // verify
108+ verifyInOrder ([
109+ // set loading state
110+ // * use a matcher since AsyncLoading != AsyncLoading with data
111+ () => listener (data, any (that: isA <AsyncLoading >())),
112+ // error when complete
113+ () => listener (
114+ any (that: isA <AsyncLoading >()), any (that: isA <AsyncError >())),
115+ ]);
116+ verifyNoMoreInteractions (listener);
60117 verify (authRepository.signOut).called (1 );
61118 });
62119 });
0 commit comments