Skip to content

Commit 94d996c

Browse files
committed
Added unit test for auth_cubit.dart and auth_service
1 parent e2b4023 commit 94d996c

File tree

9 files changed

+159
-22
lines changed

9 files changed

+159
-22
lines changed

app/lib/main/app.dart

+2-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class App extends StatelessWidget {
2424
return MultiBlocProvider(
2525
providers: [
2626
BlocProvider(create: (_) => getIt<AppCubit>()),
27-
BlocProvider(create: (_) => getIt<SessionCubit>()),
27+
BlocProvider(create: (_) => getIt<AuthCubit>()),
2828
],
2929
child: BlocBuilder<AppCubit, AppState>(
3030
builder: (context, state) {
@@ -39,7 +39,7 @@ class App extends StatelessWidget {
3939
GlobalCupertinoLocalizations.delegate,
4040
],
4141
builder: (context, child) {
42-
return BlocListener<SessionCubit, Resource>(
42+
return BlocListener<AuthCubit, Resource>(
4343
listener: (_, state) {
4444
if (state is Success<AuthState>) {
4545
switch (state.data) {

app/lib/presentation/ui/pages/login/login_page.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class _Loading extends StatelessWidget {
5656

5757
@override
5858
Widget build(BuildContext context) {
59-
return BlocBuilder<SessionCubit, Resource>(
59+
return BlocBuilder<AuthCubit, Resource>(
6060
builder: (context, state) {
6161
return LoadingScreen(
6262
isLoading: state is Loading,
+2-13
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import 'package:common/core/failure/failure.dart';
22
import 'package:common/core/resource.dart';
3-
import 'package:common/core/result_type.dart';
43
import 'package:domain/bloc/BaseBlocState.dart';
54
import 'package:domain/bloc/auth/auth_state.dart';
65

7-
class SessionCubit extends BaseBlocState<AuthState, Failure> {
8-
SessionCubit() : super(Success(AuthStateUnknown()));
6+
class AuthCubit extends BaseBlocState<AuthState, Failure> {
7+
AuthCubit() : super(Success(AuthStateUnknown()));
98

109
void isLogin() {
1110
isSuccess(AuthStateAuthenticated());
@@ -18,14 +17,4 @@ class SessionCubit extends BaseBlocState<AuthState, Failure> {
1817
void isUnknown() {
1918
isSuccess(AuthStateUnknown());
2019
}
21-
22-
@override
23-
void onResult(ResultType<void, Failure> result) {
24-
switch (result) {
25-
case TSuccess<void, Failure> _:
26-
isLogin();
27-
case TError<void, Failure> _:
28-
isError(result.error);
29-
}
30-
}
3120
}

modules/domain/lib/bloc/auth/auth_state.dart

+5
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,8 @@ class AuthStateAuthenticated extends AuthState {
1616
class AuthStateUnauthenticated extends AuthState {
1717
AuthStateUnauthenticated() : super._(AuthStatus.unauthenticated);
1818
}
19+
20+
class AuthStateError extends AuthState {
21+
final String message;
22+
AuthStateError(this.message) : super._(AuthStatus.unknown);
23+
}

modules/domain/lib/init.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class DomainInit {
77
static Future<void> initialize(GetIt getIt) async {
88
//Cubits
99
getIt.registerSingleton(AppCubit(getIt()));
10-
getIt.registerSingleton(SessionCubit());
10+
getIt.registerSingleton(AuthCubit());
1111

1212
//Services
1313
getIt.registerLazySingleton(() => AuthService(getIt(), getIt()));

modules/domain/lib/services/AuthService.dart

+11-4
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
1+
import 'package:common/core/failure/failure.dart';
2+
import 'package:common/core/result_type.dart';
13
import 'package:domain/bloc/auth/auth_cubit.dart';
24
import 'package:domain/repositories/auth_repository.dart';
35

46
class AuthService {
57
final AuthRepository _authRepository;
6-
final SessionCubit _sessionCubit;
8+
final AuthCubit _sessionCubit;
79

810
AuthService(this._authRepository, this._sessionCubit);
911

10-
void logInWithCredentials(String username, String password) async {
12+
Future<void> logInWithCredentials(String username, String password) async {
1113
_sessionCubit.isLoading();
1214
final result = await _authRepository.login(username, password);
13-
_sessionCubit.onResult(result);
15+
switch (result) {
16+
case TSuccess<void, Failure> _:
17+
_sessionCubit.isLogin();
18+
case TError<void, Failure> _:
19+
_sessionCubit.isError(result.error);
20+
}
1421
}
1522

1623
void onValidate() {
@@ -21,7 +28,7 @@ class AuthService {
2128
}
2229
}
2330

24-
void onLogout() async {
31+
Future<void> onLogout() async {
2532
await _authRepository.logout();
2633
_sessionCubit.isLogOut();
2734
}

modules/domain/pubspec.yaml

+2-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ dev_dependencies:
2424
flutter_test:
2525
sdk: flutter
2626
flutter_lints: ^2.0.0
27-
27+
bloc_test: ^9.1.0
28+
mocktail: ^1.0.0
2829
# For information on the generic Dart part of this file, see the
2930
# following page: https://dart.dev/tools/pub/pubspec
3031

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import 'package:common/core/failure/failure.dart';
2+
import 'package:common/core/result_type.dart';
3+
import 'package:domain/bloc/auth/auth_cubit.dart';
4+
import 'package:domain/repositories/auth_repository.dart';
5+
import 'package:domain/services/AuthService.dart';
6+
import 'package:flutter_test/flutter_test.dart';
7+
import 'package:mocktail/mocktail.dart';
8+
9+
class MockAuthRepository extends Mock implements AuthRepository {}
10+
11+
class MockSessionCubit extends Mock implements AuthCubit {}
12+
13+
void main() {
14+
late AuthRepository mockAuthRepository;
15+
late AuthCubit mockSessionCubit;
16+
late AuthService authService;
17+
18+
const username = 'testuser';
19+
const password = 'password123';
20+
final failure = Exception('Invalid credentials');
21+
22+
setUp(() {
23+
mockAuthRepository = MockAuthRepository();
24+
mockSessionCubit = MockSessionCubit();
25+
authService = AuthService(mockAuthRepository, mockSessionCubit);
26+
});
27+
28+
group('AuthService', () {
29+
test('logInWithCredentials calls isLogin on success', () async {
30+
when(() => mockAuthRepository.login(username, password))
31+
.thenAnswer((_) async => TSuccess(null));
32+
when(() => mockSessionCubit.isLoading()).thenReturn(null);
33+
when(() => mockSessionCubit.isLogin()).thenReturn(null);
34+
35+
await authService.logInWithCredentials(username, password);
36+
37+
verify(() => mockSessionCubit.isLoading()).called(1);
38+
verify(() => mockSessionCubit.isLogin()).called(1);
39+
verifyNever(() => mockSessionCubit.isError(any()));
40+
});
41+
42+
test('logInWithCredentials calls isError on failure', () async {
43+
when(() => mockAuthRepository.login(username, password))
44+
.thenAnswer((_) async => TError(failure));
45+
when(() => mockSessionCubit.isLoading()).thenReturn(null);
46+
when(() => mockSessionCubit.isError(failure)).thenReturn(null);
47+
48+
await authService.logInWithCredentials(username, password);
49+
50+
verify(() => mockSessionCubit.isLoading()).called(1);
51+
verify(() => mockSessionCubit.isError(failure)).called(1);
52+
verifyNever(() => mockSessionCubit.isLogin());
53+
});
54+
55+
test('onValidate calls isLogin when user is logged in', () {
56+
when(() => mockAuthRepository.isLoggedIn()).thenReturn(true);
57+
when(() => mockSessionCubit.isLogin()).thenReturn(null);
58+
59+
authService.onValidate();
60+
61+
verify(() => mockAuthRepository.isLoggedIn()).called(1);
62+
verify(() => mockSessionCubit.isLogin()).called(1);
63+
verifyNever(() => mockSessionCubit.isLogOut());
64+
});
65+
66+
test('onValidate calls isLogOut when user is not logged in', () {
67+
when(() => mockAuthRepository.isLoggedIn()).thenReturn(false);
68+
when(() => mockSessionCubit.isLogOut()).thenReturn(null);
69+
70+
authService.onValidate();
71+
72+
verify(() => mockAuthRepository.isLoggedIn()).called(1);
73+
verify(() => mockSessionCubit.isLogOut()).called(1);
74+
verifyNever(() => mockSessionCubit.isLogin());
75+
});
76+
77+
test('onLogout calls logout and then isLogOut', () async {
78+
when(() => mockAuthRepository.logout()).thenAnswer((_) async => {});
79+
when(() => mockSessionCubit.isLogOut()).thenReturn(null);
80+
81+
await authService.onLogout();
82+
83+
verify(() => mockAuthRepository.logout()).called(1);
84+
verify(() => mockSessionCubit.isLogOut()).called(1);
85+
});
86+
});
87+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import 'package:common/core/resource.dart';
2+
import 'package:domain/bloc/auth/auth_cubit.dart';
3+
import 'package:domain/bloc/auth/auth_state.dart';
4+
import 'package:flutter_test/flutter_test.dart';
5+
6+
void main() {
7+
group('SessionCubit', () {
8+
late AuthCubit cubit;
9+
10+
setUp(() {
11+
cubit = AuthCubit();
12+
});
13+
14+
tearDown(() {
15+
cubit.close();
16+
});
17+
18+
test('emits AuthStateAuthenticated when isLogin is called', () {
19+
cubit.isLogin();
20+
21+
expect(cubit.state, isA<Success<AuthState>>());
22+
23+
final successState = cubit.state as Success<AuthState>;
24+
25+
expect(successState.data, isA<AuthStateAuthenticated>());
26+
});
27+
28+
test('emits AuthStateUnauthenticated when isLogOut is called', () {
29+
cubit.isLogOut();
30+
31+
expect(cubit.state, isA<Success<AuthState>>());
32+
33+
final successState = cubit.state as Success<AuthState>;
34+
35+
expect(successState.data, isA<AuthStateUnauthenticated>());
36+
});
37+
38+
test('emits AuthStateUnknown when isUnknown is called', () {
39+
cubit.isUnknown();
40+
41+
expect(cubit.state, isA<Success<AuthState>>());
42+
43+
final successState = cubit.state as Success<AuthState>;
44+
45+
expect(successState.data, isA<AuthStateUnknown>());
46+
});
47+
});
48+
}

0 commit comments

Comments
 (0)