- 모든 *_redesign.dart 파일을 기본 화면 파일로 통합 - 백업용 컨트롤러 파일들 제거 (*_controller.backup.dart) - 사용하지 않는 예제 및 테스트 파일 제거 - Clean Architecture 적용 후 남은 정리 작업 완료 - 테스트 코드 정리 및 구조 개선 준비 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
231 lines
6.6 KiB
Dart
231 lines
6.6 KiB
Dart
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:mockito/mockito.dart';
|
|
import 'package:mockito/annotations.dart';
|
|
import 'package:dartz/dartz.dart';
|
|
import 'package:dio/dio.dart';
|
|
import 'package:superport/domain/usecases/auth/login_usecase.dart';
|
|
import 'package:superport/domain/usecases/base_usecase.dart';
|
|
import 'package:superport/services/auth_service.dart';
|
|
import 'package:superport/data/models/auth/login_request.dart';
|
|
import 'package:superport/data/models/auth/login_response.dart';
|
|
import 'package:superport/data/models/auth/auth_user.dart';
|
|
import 'package:superport/core/errors/failures.dart' as failures;
|
|
|
|
import 'login_usecase_test.mocks.dart';
|
|
|
|
@GenerateMocks([AuthService])
|
|
void main() {
|
|
late LoginUseCase loginUseCase;
|
|
late MockAuthService mockAuthService;
|
|
|
|
setUp(() {
|
|
mockAuthService = MockAuthService();
|
|
loginUseCase = LoginUseCase(mockAuthService);
|
|
});
|
|
|
|
group('LoginUseCase', () {
|
|
const tEmail = 'test@example.com';
|
|
const tPassword = 'password123!';
|
|
const tInvalidEmail = 'invalid-email';
|
|
const tEmptyPassword = '';
|
|
|
|
final tLoginRequest = LoginRequest(
|
|
email: tEmail,
|
|
password: tPassword,
|
|
);
|
|
|
|
final tLoginResponse = LoginResponse(
|
|
accessToken: 'test_access_token',
|
|
refreshToken: 'test_refresh_token',
|
|
tokenType: 'Bearer',
|
|
expiresIn: 3600,
|
|
user: AuthUser(
|
|
id: 1,
|
|
username: 'testuser',
|
|
email: tEmail,
|
|
name: 'Test User',
|
|
role: 'U',
|
|
),
|
|
);
|
|
|
|
test('로그인 성공 시 Right(LoginResponse) 반환', () async {
|
|
// arrange
|
|
when(mockAuthService.login(any))
|
|
.thenAnswer((_) async => Right(tLoginResponse));
|
|
|
|
// act
|
|
final result = await loginUseCase(
|
|
LoginParams(email: tEmail, password: tPassword),
|
|
);
|
|
|
|
// assert
|
|
expect(result, Right(tLoginResponse));
|
|
verify(mockAuthService.login(argThat(
|
|
predicate<LoginRequest>((req) =>
|
|
req.email == tEmail && req.password == tPassword),
|
|
))).called(1);
|
|
verifyNoMoreInteractions(mockAuthService);
|
|
});
|
|
|
|
test('잘못된 이메일 형식 입력 시 ValidationFailure 반환', () async {
|
|
// act
|
|
final result = await loginUseCase(
|
|
LoginParams(email: tInvalidEmail, password: tPassword),
|
|
);
|
|
|
|
// assert
|
|
expect(result.isLeft(), true);
|
|
result.fold(
|
|
(failure) {
|
|
expect(failure, isA<failures.Failure>());
|
|
expect(failure.message, '올바른 이메일 형식이 아닙니다.');
|
|
},
|
|
(_) => fail('Should return failure'),
|
|
);
|
|
verifyNever(mockAuthService.login(any));
|
|
});
|
|
|
|
test('빈 비밀번호 입력 시 ValidationFailure 반환', () async {
|
|
// act
|
|
final result = await loginUseCase(
|
|
LoginParams(email: tEmail, password: tEmptyPassword),
|
|
);
|
|
|
|
// assert
|
|
expect(result.isLeft(), true);
|
|
result.fold(
|
|
(failure) {
|
|
expect(failure, isA<failures.Failure>());
|
|
expect(failure.message, '비밀번호를 입력해주세요.');
|
|
},
|
|
(_) => fail('Should return failure'),
|
|
);
|
|
verifyNever(mockAuthService.login(any));
|
|
});
|
|
|
|
test('401 에러 시 AuthFailure 반환', () async {
|
|
// arrange
|
|
final dioError = DioException(
|
|
requestOptions: RequestOptions(path: '/login'),
|
|
response: Response(
|
|
requestOptions: RequestOptions(path: '/login'),
|
|
statusCode: 401,
|
|
),
|
|
type: DioExceptionType.badResponse,
|
|
);
|
|
|
|
when(mockAuthService.login(any)).thenThrow(dioError);
|
|
|
|
// act
|
|
final result = await loginUseCase(
|
|
LoginParams(email: tEmail, password: tPassword),
|
|
);
|
|
|
|
// assert
|
|
expect(result.isLeft(), true);
|
|
result.fold(
|
|
(failure) {
|
|
expect(failure, isA<failures.Failure>());
|
|
expect(failure.message, contains('인증'));
|
|
},
|
|
(_) => fail('Should return failure'),
|
|
);
|
|
});
|
|
|
|
test('네트워크 타임아웃 시 NetworkFailure 반환', () async {
|
|
// arrange
|
|
final dioError = DioException(
|
|
requestOptions: RequestOptions(path: '/login'),
|
|
type: DioExceptionType.connectionTimeout,
|
|
);
|
|
|
|
when(mockAuthService.login(any)).thenThrow(dioError);
|
|
|
|
// act
|
|
final result = await loginUseCase(
|
|
LoginParams(email: tEmail, password: tPassword),
|
|
);
|
|
|
|
// assert
|
|
expect(result.isLeft(), true);
|
|
result.fold(
|
|
(failure) {
|
|
expect(failure, isA<failures.Failure>());
|
|
expect(failure.message, contains('네트워크'));
|
|
},
|
|
(_) => fail('Should return failure'),
|
|
);
|
|
});
|
|
|
|
test('서버 에러 시 ServerFailure 반환', () async {
|
|
// arrange
|
|
final dioError = DioException(
|
|
requestOptions: RequestOptions(path: '/login'),
|
|
response: Response(
|
|
requestOptions: RequestOptions(path: '/login'),
|
|
statusCode: 500,
|
|
data: {'message': '서버 내부 오류'},
|
|
),
|
|
type: DioExceptionType.badResponse,
|
|
);
|
|
|
|
when(mockAuthService.login(any)).thenThrow(dioError);
|
|
|
|
// act
|
|
final result = await loginUseCase(
|
|
LoginParams(email: tEmail, password: tPassword),
|
|
);
|
|
|
|
// assert
|
|
expect(result.isLeft(), true);
|
|
result.fold(
|
|
(failure) {
|
|
expect(failure, isA<failures.Failure>());
|
|
expect(failure.message, contains('서버'));
|
|
},
|
|
(_) => fail('Should return failure'),
|
|
);
|
|
});
|
|
|
|
test('예상치 못한 에러 시 UnknownFailure 반환', () async {
|
|
// arrange
|
|
when(mockAuthService.login(any))
|
|
.thenThrow(Exception('Unexpected error'));
|
|
|
|
// act
|
|
final result = await loginUseCase(
|
|
LoginParams(email: tEmail, password: tPassword),
|
|
);
|
|
|
|
// assert
|
|
expect(result.isLeft(), true);
|
|
result.fold(
|
|
(failure) {
|
|
expect(failure, isA<failures.Failure>());
|
|
expect(failure.message, contains('오류'));
|
|
},
|
|
(_) => fail('Should return failure'),
|
|
);
|
|
});
|
|
|
|
test('로그인 실패 시 (null 반환) AuthFailure 반환', () async {
|
|
// arrange
|
|
when(mockAuthService.login(any)).thenAnswer((_) async => Left(failures.AuthenticationFailure(message: '로그인에 실패했습니다.')));
|
|
|
|
// act
|
|
final result = await loginUseCase(
|
|
LoginParams(email: tEmail, password: tPassword),
|
|
);
|
|
|
|
// assert
|
|
expect(result.isLeft(), true);
|
|
result.fold(
|
|
(failure) {
|
|
expect(failure, isA<failures.Failure>());
|
|
expect(failure.message, contains('로그인'));
|
|
},
|
|
(_) => fail('Should return failure'),
|
|
);
|
|
});
|
|
});
|
|
} |