diff --git a/lib/core/db/transaction_service.dart b/lib/core/db/transaction_service.dart index 42f92096..deadbdd4 100644 --- a/lib/core/db/transaction_service.dart +++ b/lib/core/db/transaction_service.dart @@ -1,3 +1,3 @@ abstract interface class TransactionService { - Future run(Function callBack); + Future run(Function callBack); } diff --git a/lib/core/enum/exception_code.dart b/lib/core/enum/exception_code.dart new file mode 100644 index 00000000..fb07d475 --- /dev/null +++ b/lib/core/enum/exception_code.dart @@ -0,0 +1,107 @@ +enum ExceptionCode implements Exception { + unknownException( + code: '500', + errorMessage: '알 수 없는 오류 발생', + alertMessage: '알 수 없는 오류가 발생했습니다.', + ), + internalServerException( + code: '400', + errorMessage: '서버 내부 오류', + alertMessage: '', + ), + notFoundException( + code: '404', + errorMessage: '데이터 조회 실패', + alertMessage: '', + ), + networkException( + code: '400', + errorMessage: '네트워크 요청 오류', + alertMessage: '네트워크 연결을 확인해주세요.', + ), + userNotFoundException( + code: 'user-not-found', + errorMessage: '존재하지 않는 유저입니다.', + alertMessage: '', + ), + wrongPasswordException( + code: 'wrong-password', + errorMessage: '비밀번호가 맞지 않습니다.', + alertMessage: '', + ), + emailAlreadyInUseException( + code: 'email-already-in-use', + errorMessage: '이미 가입된 이메일입니다.', + alertMessage: '', + ), + invalidEmailException( + code: 'invalid-email', + errorMessage: '이메일 형식이 올바르지 못합니다.', + alertMessage: '', + ), + weakPasswordException( + code: 'weak-password', + errorMessage: '비밀번호 형식이 안전하지 않습니다.', + alertMessage: '', + ), + networkRequestFailedException( + code: 'network-request-failed', + errorMessage: '네트워크가 불안정 합니다.', + alertMessage: '', + ), + userDisabledException( + code: 'user-disabled', + errorMessage: '이미 탈퇴한 회원입니다.', + alertMessage: '', + ), + invalidCredentialException( + code: 'invalid-credential', + errorMessage: '이메일과 비밀번호를 확인해주세요.', + alertMessage: ''), + + authenticationNotExistException( + code: 'authentication-not-exist', + errorMessage: 'FirebaseAuth 로그인 정보 없음', + alertMessage: notShowingMessage), + + locationException( + code: 'no-location', + errorMessage: '위치 정보를 가져올 수 없습니다.', + alertMessage: notShowingMessage, + ), + + kakaoGeoCoderApiException( + code: 'kakao-geo-coder-api-error', + errorMessage: 'Kakao Api 처리 오류', + alertMessage: notShowingMessage, + ); + + final String code; + final String errorMessage; + final String alertMessage; + static const String notShowingMessage = ''; + + const ExceptionCode({ + required this.code, + required this.alertMessage, + required this.errorMessage, + }); + + static ExceptionCode fromStatus(String status) { + if (int.tryParse(status) != null) return ExceptionCode.internalServerException; + return switch (status) { + 'user-not-found' => ExceptionCode.userNotFoundException, + 'wrong-password' => ExceptionCode.wrongPasswordException, + 'email-already-in-use' => ExceptionCode.emailAlreadyInUseException, + 'invalid-email' => ExceptionCode.invalidEmailException, + 'weak-password' => ExceptionCode.weakPasswordException, + 'network-request-failed' => ExceptionCode.networkRequestFailedException, + 'user-disabled' => ExceptionCode.userDisabledException, + 'invaild-credential' => ExceptionCode.invalidCredentialException, + 'authentication-not-exist' => ExceptionCode.authenticationNotExistException, + 'no-location' => ExceptionCode.locationException, + 'kakao-geo-coder-api-error' => ExceptionCode.kakaoGeoCoderApiException, + _ => ExceptionCode.unknownException, + }; + } +} diff --git a/lib/core/exception/authentication_exception.dart b/lib/core/exception/authentication_exception.dart new file mode 100644 index 00000000..a23fd0e1 --- /dev/null +++ b/lib/core/exception/authentication_exception.dart @@ -0,0 +1,6 @@ +import 'package:weaco/core/exception/custom_business_exception.dart'; + +class AuthenticationException extends CustomBusinessException { + AuthenticationException( + {required super.code, required super.message}); +} diff --git a/lib/core/exception/custom_business_exception.dart b/lib/core/exception/custom_business_exception.dart index 6a233266..6f18ed98 100644 --- a/lib/core/exception/custom_business_exception.dart +++ b/lib/core/exception/custom_business_exception.dart @@ -1,6 +1,8 @@ +import 'package:weaco/core/enum/exception_code.dart'; + /// 어플리케이션 비지니스상 의도한 예외를 정의한 클래스 class CustomBusinessException implements Exception { - final int code; + final ExceptionCode code; final String message; CustomBusinessException({required this.code, required this.message}); diff --git a/lib/core/exception/location_exception.dart b/lib/core/exception/location_exception.dart new file mode 100644 index 00000000..32635949 --- /dev/null +++ b/lib/core/exception/location_exception.dart @@ -0,0 +1,6 @@ +import 'package:weaco/core/exception/custom_business_exception.dart'; + +/// GPS 정보에 접근할 수 없음 예외 +class LocationException extends CustomBusinessException { + LocationException({required super.code, required super.message}); +} diff --git a/lib/core/exception/network_exception.dart b/lib/core/exception/network_exception.dart index ec30daff..3a5869d2 100644 --- a/lib/core/exception/network_exception.dart +++ b/lib/core/exception/network_exception.dart @@ -1,28 +1,5 @@ -sealed class NetworkException implements Exception { - final String code; - final String message; +import 'package:weaco/core/exception/custom_business_exception.dart'; - NetworkException({required this.code, required this.message}); - - factory NetworkException.noData( - {required String code, required String message}) = NoDataException; - - factory NetworkException.errorCode( - {required String code, - required String message}) = ErrorResponseCodeException; - - factory NetworkException.unknown( - {required String code, required String message}) = UnknownException; -} - -class NoDataException extends NetworkException { - NoDataException({required super.code, required super.message}); -} - -class ErrorResponseCodeException extends NetworkException { - ErrorResponseCodeException({required super.code, required super.message}); -} - -class UnknownException extends NetworkException { - UnknownException({required super.code, required super.message}); +class NetworkException extends CustomBusinessException { + NetworkException({required super.code, required super.message}); } diff --git a/lib/core/gps/gps_helper.dart b/lib/core/gps/gps_helper.dart index badc92b8..ae47e0ab 100644 --- a/lib/core/gps/gps_helper.dart +++ b/lib/core/gps/gps_helper.dart @@ -1,5 +1,6 @@ import 'dart:developer'; import 'package:geolocator/geolocator.dart'; +import 'package:weaco/core/enum/exception_code.dart'; import 'package:weaco/core/gps/gps_permission_status.dart'; import 'package:weaco/core/gps/gps_position.dart'; @@ -43,7 +44,6 @@ class GpsHelper { Position position = await Geolocator.getCurrentPosition(); return GpsPosition(lat: position.latitude, lng: position.longitude); } - // Todo: 커스텀 Exception으로 리팩토링 필요 - throw Exception('권한 없음'); + throw ExceptionCode.locationException; } } diff --git a/lib/data/common/http/status_code_handler.dart b/lib/data/common/http/status_code_handler.dart index 4e569403..35e65f75 100644 --- a/lib/data/common/http/status_code_handler.dart +++ b/lib/data/common/http/status_code_handler.dart @@ -1,3 +1,4 @@ +import 'package:weaco/core/enum/exception_code.dart'; import 'package:weaco/core/exception/custom_business_exception.dart'; import 'package:weaco/core/exception/internal_server_exception.dart'; @@ -7,8 +8,8 @@ import '../../../core/exception/not_found_exception.dart'; CustomBusinessException statusCodeHandler({int? code, String? message}) { return switch (code) { 404 => NotFoundException( - code: code!, message: message ?? 'Data Not Found Error'), + code: ExceptionCode.unknownException, message: message ?? 'Data Not Found Error'), _ => InternalServerException( - code: code ?? 500, message: message ?? 'Internal Server Error'), + code: ExceptionCode.internalServerException, message: message ?? 'Internal Server Error'), }; } diff --git a/lib/data/feed/data_source/remote_feed_data_source.dart b/lib/data/feed/data_source/remote_feed_data_source.dart index 81572826..2ba0df16 100644 --- a/lib/data/feed/data_source/remote_feed_data_source.dart +++ b/lib/data/feed/data_source/remote_feed_data_source.dart @@ -6,7 +6,8 @@ abstract interface class RemoteFeedDataSource { /// OOTD 피드 작성 성공 시 : 피드 업로드 요청(Feed) -> / 업로드 완료(bool) ← 파베 /// OOTD 편집 완료 후 [상세 페이지]: 위와 동일. /// OOTD 편집 완료 후 [마이 페이지]: 위와 동일.*피드 업데이트 - Future saveFeed({ + + Future saveFeed({ required Transaction transaction, required Feed feed, }); @@ -22,7 +23,7 @@ abstract interface class RemoteFeedDataSource { }); /// [마이페이지] 피드 삭제: 피드 삭제 요청(id) -> 파베/ 삭제 완료 (bool) from FB - Future deleteFeed({ + Future deleteFeed({ required Transaction transaction, required String id, }); diff --git a/lib/data/feed/data_source/remote_feed_data_source_impl.dart b/lib/data/feed/data_source/remote_feed_data_source_impl.dart index 3e7763fa..2443258b 100644 --- a/lib/data/feed/data_source/remote_feed_data_source_impl.dart +++ b/lib/data/feed/data_source/remote_feed_data_source_impl.dart @@ -1,4 +1,8 @@ import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:dio/dio.dart'; +import 'package:weaco/core/enum/exception_code.dart'; +import 'package:weaco/core/exception/internal_server_exception.dart'; +import 'package:weaco/core/exception/network_exception.dart'; import 'package:weaco/core/exception/not_found_exception.dart'; import 'package:weaco/core/firebase/firestore_dto_mapper.dart'; import 'package:weaco/data/feed/data_source/remote_feed_data_source.dart'; @@ -14,38 +18,47 @@ class RemoteFeedDataSourceImpl implements RemoteFeedDataSource { /// OOTD 피드 작성 또는 편집 후 저장 @override - Future saveFeed({ + Future saveFeed({ required Transaction transaction, required Feed feed, }) async { final feedDto = toFeedDto(feed: feed); - if (feed.id != null) { - // 피드를 수정할 경우 - final feedDocRef = _fireStore.collection('feeds').doc(feed.id); - transaction.set(feedDocRef, feedDto); - } else { - // 새 피드를 추가할 경우 + try { + // 피드를 수정 할 경우 + if (feed.id != null) { + final feedDocRef = _fireStore.collection('feeds').doc(feed.id); + + transaction.set(feedDocRef, feedDto); + return; + } + + // 새 피드를 저장 할 경우 final feedDocRef = _fireStore.collection('feeds').doc(); transaction.set(feedDocRef, feedDto); + } catch (e) { + _exceptionHandling(e); } - return true; } /// [OOTD 피드 상세 페이지]: /// 피드 데이터 요청 (id) -> 파베 / 피드 데이터 반환(json) ← 파베 @override Future getFeed({required String id}) async { - final docSnapshot = await _fireStore.collection('feeds').doc(id).get(); - - if (docSnapshot.data() == null) { - throw NotFoundException( - code: 500, - message: '피드가 존재하지 않습니다.', - ); + try { + final docSnapshot = await _fireStore.collection('feeds').doc(id).get(); + + if (docSnapshot.data() == null) { + throw NotFoundException( + code: ExceptionCode.notFoundException, + message: '피드가 존재하지 않습니다.', + ); + } + + return toFeed(json: docSnapshot.data()!, id: docSnapshot.id); + } catch (e) { + throw _exceptionHandling(e); } - - return toFeed(json: docSnapshot.data()!, id: docSnapshot.id); } /// [유저 페이지/마이 페이지]: @@ -56,42 +69,55 @@ class RemoteFeedDataSourceImpl implements RemoteFeedDataSource { DateTime? createdAt, required int limit, }) async { - final querySnapshot = await _fireStore - .collection('feeds') - .where('user_email', isEqualTo: email) - .where('deleted_at', isNull: true) - .where('created_at', - isLessThan: createdAt ?? Timestamp.fromDate(DateTime.now())) - .orderBy('created_at', descending: true) - .limit(limit) - .get(); - - return querySnapshot.docs - .map((doc) => toFeed(json: doc.data(), id: doc.id)) - .toList(); + try { + final querySnapshot = await _fireStore + .collection('feeds') + .where('user_email', isEqualTo: email) + .where('deleted_at', isNull: true) + .where('created_at', + isLessThan: createdAt ?? Timestamp.fromDate(DateTime.now())) + .orderBy('created_at', descending: true) + .limit(limit) + .get(); + + if (querySnapshot.docs.isEmpty) { + throw NotFoundException( + code: ExceptionCode.notFoundException, + message: '피드가 존재하지 않습니다.', + ); + } + + return querySnapshot.docs + .map((doc) => toFeed(json: doc.data(), id: doc.id)) + .toList(); + } catch (e) { + throw _exceptionHandling(e); + } } /// [마이페이지] 피드 삭제 /// soft delete 처리 @override - Future deleteFeed({ + Future deleteFeed({ required Transaction transaction, required String id, }) async { - final originalFeedDocRef = _fireStore.collection('feeds').doc(id); - final originalFeedDoc = await originalFeedDocRef.get(); - - if (originalFeedDoc.exists) { - final feed = toFeed(json: originalFeedDoc.data()!, id: id); - final deletedFeed = feed.copyWith(deletedAt: DateTime.now()); - - transaction.update( - originalFeedDocRef, - toFeedDto(feed: deletedFeed), - ); + try { + final originalFeedDocRef = _fireStore.collection('feeds').doc(id); + final originalFeedDoc = await originalFeedDocRef.get(); + + if (originalFeedDoc.exists) { + final feed = toFeed(json: originalFeedDoc.data()!, id: id); + final deletedFeed = feed.copyWith(deletedAt: DateTime.now()); + + transaction.update( + originalFeedDocRef, + toFeedDto(feed: deletedFeed), + ); + } + } catch (e) { + _exceptionHandling(e); } - - return true; } /// [홈 페이지] 하단 OOTD 추천: @@ -103,25 +129,30 @@ class RemoteFeedDataSourceImpl implements RemoteFeedDataSource { DateTime? createdAt}) async { final index = DateTime.now().hour; final weather = dailyLocationWeather.weatherList[index]; - final querySnapshot = await _fireStore - .collection('feeds') - .where('weather.code', isEqualTo: weather.code) - // .where('season_code', isEqualTo: dailyLocationWeather.seasonCode) - .where( - 'weather.temperature', - isLessThanOrEqualTo: dailyLocationWeather.highTemperature, - isGreaterThanOrEqualTo: dailyLocationWeather.lowTemperature, - ) - .where('created_at', - isLessThan: createdAt ?? Timestamp.fromDate(DateTime.now())) - .where('deleted_at', isNull: true) - .orderBy('created_at', descending: true) - .limit(10) - .get(); - - return querySnapshot.docs - .map((doc) => toFeed(json: doc.data(), id: doc.id)) - .toList(); + + try { + final querySnapshot = await _fireStore + .collection('feeds') + .where('weather.code', isEqualTo: weather.code) + // .where('season_code', isEqualTo: dailyLocationWeather.seasonCode) + .where( + 'weather.temperature', + isLessThanOrEqualTo: dailyLocationWeather.highTemperature, + isGreaterThanOrEqualTo: dailyLocationWeather.lowTemperature, + ) + .where('created_at', + isLessThan: createdAt ?? Timestamp.fromDate(DateTime.now())) + .where('deleted_at', isNull: true) + .orderBy('created_at', descending: true) + .limit(10) + .get(); + + return querySnapshot.docs + .map((doc) => toFeed(json: doc.data(), id: doc.id)) + .toList(); + } catch (e) { + throw _exceptionHandling(e); + } } /// [검색 페이지] 피드 검색: @@ -137,38 +168,57 @@ class RemoteFeedDataSourceImpl implements RemoteFeedDataSource { int? minTemperature, int? maxTemperature, }) async { - Query> query = _fireStore.collection('feeds'); - // 날씨 코드 필터링 - if (weatherCode != null) { - query = query.where('weather.code', isEqualTo: weatherCode); - } - - // 온도 범위 필터링 - if (minTemperature != null && maxTemperature != null) { - query = query - .where('weather.temperature', isLessThanOrEqualTo: maxTemperature) - .where('weather.temperature', isGreaterThanOrEqualTo: minTemperature); + try { + Query> query = _fireStore.collection('feeds'); + // 날씨 코드 필터링 + if (weatherCode != null) { + query = query.where('weather.code', isEqualTo: weatherCode); + } + + // 온도 범위 필터링 + if (minTemperature != null && maxTemperature != null) { + query = query + .where('weather.temperature', isLessThanOrEqualTo: maxTemperature) + .where('weather.temperature', + isGreaterThanOrEqualTo: minTemperature); + } + + // 계절 코드 필터링 + if (seasonCode != null) { + query = query.where('season_code', isEqualTo: seasonCode); + } + + // 생성일 기준으로 정렬하여 제한된 수의 문서 가져오기 + final QuerySnapshot> querySnapshot = await query + .where('created_at', + isLessThan: createdAt ?? Timestamp.fromDate(DateTime.now())) + .where('deleted_at', isNull: true) + .orderBy( + 'created_at', + descending: true, + ) + .limit(limit) + .get(); + + return querySnapshot.docs + .map((doc) => toFeed(json: doc.data(), id: doc.id)) + .toList(); + } catch (e) { + throw _exceptionHandling(e); } + } - // 계절 코드 필터링 - if (seasonCode != null) { - query = query.where('season_code', isEqualTo: seasonCode); + Exception _exceptionHandling(Object e) { + switch (e) { + case FirebaseException _: + return InternalServerException( + code: ExceptionCode.internalServerException, message: '서버 내부 오류'); + case DioException _: + return NetworkException( + code: ExceptionCode.internalServerException, + message: '네트워크 오류 : $e'); + default: + return e as Exception; } - - // 생성일 기준으로 정렬하여 제한된 수의 문서 가져오기 - final QuerySnapshot> querySnapshot = await query - .where('created_at', - isLessThan: createdAt ?? Timestamp.fromDate(DateTime.now())) - .where('deleted_at', isNull: true) - .orderBy( - 'created_at', - descending: true, - ) - .limit(limit) - .get(); - - return querySnapshot.docs - .map((doc) => toFeed(json: doc.data(), id: doc.id)) - .toList(); } } diff --git a/lib/data/feed/repository/feed_repository_impl.dart b/lib/data/feed/repository/feed_repository_impl.dart index a4e24e72..530be8ec 100644 --- a/lib/data/feed/repository/feed_repository_impl.dart +++ b/lib/data/feed/repository/feed_repository_impl.dart @@ -15,7 +15,7 @@ class FeedRepositoryImpl implements FeedRepository { /// @param id: 피드 id /// @return Feed: 피드 @override - Future getFeed({required String id}) async { + Future getFeed({required String id}) async { return await remoteFeedDataSource.getFeed(id: id); } diff --git a/lib/data/feed/repository/ootd_feed_repository_impl.dart b/lib/data/feed/repository/ootd_feed_repository_impl.dart index 59c9a393..3d8dccb9 100644 --- a/lib/data/feed/repository/ootd_feed_repository_impl.dart +++ b/lib/data/feed/repository/ootd_feed_repository_impl.dart @@ -26,16 +26,16 @@ class OotdFeedRepositoryImpl implements OotdFeedRepository { /// 피드 저장 및 수정 @override - Future saveOotdFeed({required Feed feed}) async { - return _firestoreService.run((Transaction transaction) async { - return feed.id == null + Future saveOotdFeed({required Feed feed}) async { + await _firestoreService.run((Transaction transaction) async { + feed.id == null ? await _save(transaction: transaction, feed: feed) : await _update(transaction: transaction, feed: feed); }); } /// 피드 저장 - Future _save({ + Future _save({ required Transaction transaction, required Feed feed, }) async { @@ -50,27 +50,23 @@ class OotdFeedRepositoryImpl implements OotdFeedRepository { transaction: transaction, count: 1, ); - - return true; } /// 피드 수정 - Future _update({ + Future _update({ required Transaction transaction, required Feed feed, }) async { - final updateResult = await _remoteFeedDataSource.saveFeed( + await _remoteFeedDataSource.saveFeed( transaction: transaction, feed: feed, ); - - return updateResult; } /// 피드 삭제 @override - Future removeOotdFeed({required String id}) async { - return _firestoreService.run((Transaction transaction) async { + Future removeOotdFeed({required String id}) async { + await _firestoreService.run((Transaction transaction) async { await _remoteFeedDataSource.deleteFeed( transaction: transaction, id: id, @@ -80,8 +76,6 @@ class OotdFeedRepositoryImpl implements OotdFeedRepository { transaction: transaction, count: -1, ); - - return true; }); } diff --git a/lib/data/file/data_source/local/local_file_data_source.dart b/lib/data/file/data_source/local/local_file_data_source.dart index f58a75bf..8e19bcde 100644 --- a/lib/data/file/data_source/local/local_file_data_source.dart +++ b/lib/data/file/data_source/local/local_file_data_source.dart @@ -3,11 +3,11 @@ import 'dart:io'; import 'package:weaco/core/enum/image_type.dart'; abstract interface class LocalFileDataSource { - Future getImage({required ImageType imageType}); + Future getImage({required ImageType imageType}); - Future saveImage({required bool isOrigin, required File file}); + Future saveImage({required bool isOrigin, required File file}); - Future getCompressedImage(); + Future getCompressedImage(); Future saveCompressedImage({required List image}); diff --git a/lib/data/file/data_source/local/local_file_data_source_impl.dart b/lib/data/file/data_source/local/local_file_data_source_impl.dart index d5471963..c7240887 100644 --- a/lib/data/file/data_source/local/local_file_data_source_impl.dart +++ b/lib/data/file/data_source/local/local_file_data_source_impl.dart @@ -1,5 +1,7 @@ -import 'dart:developer'; import 'dart:io'; +import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:dio/dio.dart'; +import 'package:weaco/core/enum/exception_code.dart'; import 'package:weaco/core/enum/image_type.dart'; import 'package:weaco/core/path_provider/path_provider_service.dart'; import 'local_file_data_source.dart'; @@ -14,25 +16,24 @@ class LocalFileDataSourceImpl implements LocalFileDataSource { : _pathProvider = pathProvider; @override - Future getImage({required ImageType imageType}) async { + Future getImage({required ImageType imageType}) async { try { final directory = await _pathProvider.getCacheDirectory(); - String fileName = switch(imageType) { - ImageType.origin => _originImageFileName , + String fileName = switch (imageType) { + ImageType.origin => _originImageFileName, ImageType.cropped => _croppedImageFileName, ImageType.compressed => _compressedImageFileName, }; - return (await File('$directory/$fileName').exists()) - ? File('$directory/$fileName') - : null; + if (!await File('$directory/$fileName').exists()) throw ExceptionCode.notFoundException; + + return File('$directory/$fileName'); } catch (e) { - log(e.toString(), name: 'LocalFileDataSourceImpl.getImagePath()'); - return null; + throw _exceptionHandling(e); } } @override - Future saveImage({required bool isOrigin, required File file}) async { + Future saveImage({required bool isOrigin, required File file}) async { try { final directory = await _pathProvider.getCacheDirectory(); String fileName = isOrigin ? _originImageFileName : _croppedImageFileName; @@ -40,23 +41,20 @@ class LocalFileDataSourceImpl implements LocalFileDataSource { await File('$directory/$fileName').delete(); } await File('$directory/$fileName').writeAsBytes(await file.readAsBytes()); - return true; } catch (e) { - log(e.toString(), name: 'LocalFileDataSourceImpl.saveImage()'); - return false; + _exceptionHandling(e); } } @override - Future getCompressedImage() async { + Future getCompressedImage() async { try { final directory = await _pathProvider.getCacheDirectory(); - return (await File('$directory/$_compressedImageFileName').exists()) - ? File('$directory/$_compressedImageFileName') - : null; + await File('$directory/$_compressedImageFileName').exists(); + + return File('$directory/$_compressedImageFileName'); } catch (e) { - log(e.toString(), name: 'LocalFileDataSourceImpl.getCompressedImage()'); - return null; + throw _exceptionHandling(e); } } @@ -69,7 +67,16 @@ class LocalFileDataSourceImpl implements LocalFileDataSource { } await File('$directory/$_compressedImageFileName').writeAsBytes(image); } catch (e) { - log(e.toString(), name: 'LocalFileDataSourceImpl.saveCompressedImage()'); + _exceptionHandling(e); } } + + ExceptionCode _exceptionHandling(Object e) { + return switch (e) { + FirebaseException _ => ExceptionCode.internalServerException, + DioException _ => ExceptionCode.internalServerException, + ExceptionCode _ => e, + _ => ExceptionCode.unknownException, + }; + } } diff --git a/lib/data/file/data_source/remote/remote_file_data_source_impl.dart b/lib/data/file/data_source/remote/remote_file_data_source_impl.dart index 511bc7c8..a0319f70 100644 --- a/lib/data/file/data_source/remote/remote_file_data_source_impl.dart +++ b/lib/data/file/data_source/remote/remote_file_data_source_impl.dart @@ -1,6 +1,7 @@ import 'dart:io'; - +import 'package:dio/dio.dart'; import 'package:firebase_storage/firebase_storage.dart'; +import 'package:weaco/core/enum/exception_code.dart'; import 'package:weaco/core/firebase/firebase_auth_service.dart'; import 'package:weaco/data/file/data_source/remote/remote_file_data_source.dart'; @@ -17,21 +18,33 @@ class RemoteFileDataSourceImpl implements RemoteFileDataSource { @override Future> saveImage( {required File croppedImage, required File compressedImage}) async { - final String? email = _firebaseAuthService.firebaseAuth.currentUser?.email; - if (email == null) throw Exception(); - final feedOriginImageRef = _firebaseStorage.ref().child( - 'feed_origin_images/${email}_${DateTime.now().microsecondsSinceEpoch}.png'); - final feedThumbnailImageRef = _firebaseStorage.ref().child( - 'feed_thumbnail_images/${email}_${DateTime.now().microsecondsSinceEpoch}.png'); + try { + final String? email = + _firebaseAuthService.firebaseAuth.currentUser?.email; + if (email == null) { + throw ExceptionCode.authenticationNotExistException; + } + final feedOriginImageRef = _firebaseStorage.ref().child( + 'feed_origin_images/${email}_${DateTime.now().microsecondsSinceEpoch}.png'); + + final feedThumbnailImageRef = _firebaseStorage.ref().child( + 'feed_thumbnail_images/${email}_${DateTime.now().microsecondsSinceEpoch}.png'); - await Future.wait([ - feedOriginImageRef.putFile(croppedImage), - feedThumbnailImageRef.putFile(compressedImage), - ]); + await Future.wait([ + feedOriginImageRef.putFile(croppedImage), + feedThumbnailImageRef.putFile(compressedImage), + ]); - return await Future.wait([ - feedOriginImageRef.getDownloadURL(), - feedThumbnailImageRef.getDownloadURL() - ]); + return await Future.wait([ + feedOriginImageRef.getDownloadURL(), + feedThumbnailImageRef.getDownloadURL() + ]); + } catch (e) { + throw switch (e) { + FirebaseException _ => ExceptionCode.internalServerException, + DioException _ => ExceptionCode.networkException, + _ => e, + }; + } } } diff --git a/lib/data/file/repository/file_repository_impl.dart b/lib/data/file/repository/file_repository_impl.dart index 69e9c71c..bfa19f69 100644 --- a/lib/data/file/repository/file_repository_impl.dart +++ b/lib/data/file/repository/file_repository_impl.dart @@ -15,22 +15,21 @@ class FileRepositoryImpl implements FileRepository { _remoteFileDataSource = remoteFileDataSource; @override - Future getImage({required ImageType imageType}) async { + Future getImage({required ImageType imageType}) async { return await _localFileDataSource.getImage(imageType: imageType); } @override - Future saveImage({required bool isOrigin, required File file, required List compressedImage}) async { + Future saveImage({required bool isOrigin, required File file, required List compressedImage}) async { await _localFileDataSource.saveCompressedImage(image: compressedImage); - return await _localFileDataSource.saveImage(isOrigin: isOrigin, file: file); + await _localFileDataSource.saveImage(isOrigin: isOrigin, file: file); } @override Future> saveOotdImage() async { - final File? croppedImage = await _localFileDataSource.getImage(imageType: ImageType.cropped); - final File? compressedImage = await _localFileDataSource.getImage(imageType: ImageType.compressed); - if (croppedImage == null || compressedImage == null) throw Exception(); + final File croppedImage = await _localFileDataSource.getImage(imageType: ImageType.cropped); + final File compressedImage = await _localFileDataSource.getImage(imageType: ImageType.compressed); return await _remoteFileDataSource.saveImage(croppedImage: croppedImage, compressedImage: compressedImage); } } diff --git a/lib/data/location/data_source/remote_data_source/kakao_reverse_geo_coder_api.dart b/lib/data/location/data_source/remote_data_source/kakao_reverse_geo_coder_api.dart index 7756b034..e447b065 100644 --- a/lib/data/location/data_source/remote_data_source/kakao_reverse_geo_coder_api.dart +++ b/lib/data/location/data_source/remote_data_source/kakao_reverse_geo_coder_api.dart @@ -1,8 +1,8 @@ -import 'dart:developer'; +import 'package:dio/dio.dart'; import 'package:weaco/core/config/kakao_config.dart'; import 'package:weaco/core/dio/base_dio.dart'; import 'package:weaco/core/dio/base_response.dart'; -import 'package:weaco/core/exception/network_exception.dart'; +import 'package:weaco/core/enum/exception_code.dart'; import 'package:weaco/data/location/data_source/remote_data_source/remote_location_data_source.dart'; class KakaoReverseGeoCoderApi implements RemoteLocationDataSource { @@ -28,23 +28,17 @@ class KakaoReverseGeoCoderApi implements RemoteLocationDataSource { receiveTimeout: const Duration(seconds: 2)); if (result.statusCode == 200) { if (result.body['meta']['total_count'] == 0) { - throw NetworkException.noData( - code: 'EmptyData', message: '응답 데이터 없음'); + throw ExceptionCode.notFoundException; } else { return '${result.body['documents'][0]['region_1depth_name']} ${result.body['documents'][0]['region_2depth_name']}'; } } - throw NetworkException.errorCode( - code: result.statusCode.toString(), message: '네트워크 응답 에러'); + throw ExceptionCode.kakaoGeoCoderApiException; } catch (e) { - log(e.toString(), name: 'ReverseGeoCoderHelper.getDong()'); - switch (e) { - case NoDataException _ || ErrorResponseCodeException _: - rethrow; - default: - throw NetworkException.unknown( - code: 'Unknown', message: e.toString()); - } + throw switch (e) { + DioException _ => ExceptionCode.networkException, + _ => e, + }; } } } diff --git a/lib/data/user/data_source/firebase_user_auth_data_source.dart b/lib/data/user/data_source/firebase_user_auth_data_source.dart index e8609024..420bbde0 100644 --- a/lib/data/user/data_source/firebase_user_auth_data_source.dart +++ b/lib/data/user/data_source/firebase_user_auth_data_source.dart @@ -1,5 +1,8 @@ import 'dart:developer'; +import 'package:dio/dio.dart'; +import 'package:firebase_core/firebase_core.dart'; +import 'package:weaco/core/enum/exception_code.dart'; import 'package:weaco/core/firebase/firebase_auth_service.dart'; import 'package:weaco/data/user/data_source/user_auth_data_source.dart'; @@ -12,70 +15,62 @@ class FirebaseUserAuthDataSourceImpl implements UserAuthDataSource { // 회원가입 @override - Future signUp({required String email, required String password}) async { - bool isSignUpSuccess = false; - + Future signUp({required String email, required String password}) async { try { - final userCredential = - await _firebaseService.signUp(email: email, password: password); - - isSignUpSuccess = userCredential?.user != null; - } on Exception catch (e) { - isSignUpSuccess = false; + await _firebaseService.signUp(email: email, password: password); + } catch (e) { log(e.toString(), name: 'FirebaseUserAuthDataSource.signUp()'); - rethrow; + throw _exceptionHandling(e); } - - return isSignUpSuccess; } // 로그인 @override - Future signIn({required String email, required String password}) async { + Future signIn({required String email, required String password}) async { try { await _firebaseService.signIn(email: email, password: password); - } on Exception catch (e) { + } catch (e) { log(e.toString(), name: 'FirebaseUserAuthDataSource.signIn()'); - rethrow; + throw _exceptionHandling(e); } - - return true; } // 로그아웃 @override - Future logOut() async { - bool isLogOutSuccess = true; - + Future logOut() async { try { await _firebaseService.logOut(); - } on Exception catch (e) { - isLogOutSuccess = false; + } catch (e) { log(e.toString(), name: 'FirebaseUserAuthDataSource.logOut()'); - rethrow; + throw _exceptionHandling(e); } - - return isLogOutSuccess; } // 회원탈퇴 @override - Future signOut() async { - bool isSignOutSuccess = true; - + Future signOut() async { try { await _firebaseService.signOut(); - } on Exception catch (e) { - isSignOutSuccess = false; + } catch (e) { log(e.toString(), name: 'FirebaseUserAuthDataSource.signOut()'); - rethrow; + throw _exceptionHandling(e); } - - return isSignOutSuccess; } @override String? signInCheck() { - return _firebaseService.user?.email; + try { + return _firebaseService.user?.email; + } catch (e) { + throw _exceptionHandling(e); + } + } + + ExceptionCode _exceptionHandling(Object e) { + return switch (e) { + FirebaseException fb => ExceptionCode.fromStatus(fb.code), + DioException _ => ExceptionCode.internalServerException, + _ => ExceptionCode.unknownException, + }; } } diff --git a/lib/data/user/data_source/remote_user_profile_data_source.dart b/lib/data/user/data_source/remote_user_profile_data_source.dart index db66618a..3ebdf2ff 100644 --- a/lib/data/user/data_source/remote_user_profile_data_source.dart +++ b/lib/data/user/data_source/remote_user_profile_data_source.dart @@ -7,14 +7,14 @@ abstract interface class RemoteUserProfileDataSource { Future getUserProfile({String email}); /// 유저 프로필 업데이트 (피드 갯수 수정 할 때 주로 쓰임) - Future updateUserProfile({ + Future updateUserProfile({ required Transaction transaction, required UserProfile userProfile, }); /// 유저 프로필 저장 - Future saveUserProfile({required UserProfile userProfile}); + Future saveUserProfile({required UserProfile userProfile}); /// 유저 프로필 삭제 - Future removeUserProfile(); + Future removeUserProfile({String? email}); } diff --git a/lib/data/user/data_source/remote_user_profile_date_source_impl.dart b/lib/data/user/data_source/remote_user_profile_date_source_impl.dart index 09f42ec1..8046d964 100644 --- a/lib/data/user/data_source/remote_user_profile_date_source_impl.dart +++ b/lib/data/user/data_source/remote_user_profile_date_source_impl.dart @@ -1,4 +1,8 @@ import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:dio/dio.dart'; +import 'package:weaco/core/enum/exception_code.dart'; +import 'package:weaco/core/exception/internal_server_exception.dart'; +import 'package:weaco/core/exception/network_exception.dart'; import 'package:weaco/core/firebase/firebase_auth_service.dart'; import 'package:weaco/core/firebase/firestore_dto_mapper.dart'; import 'package:weaco/data/user/data_source/remote_user_profile_data_source.dart'; @@ -15,38 +19,34 @@ class RemoteUserProfileDataSourceImpl implements RemoteUserProfileDataSource { _firebaseService = firebaseService; @override - Future saveUserProfile({required UserProfile userProfile}) async { + Future saveUserProfile({required UserProfile userProfile}) async { try { - return await _firestore + await _firestore .collection('user_profiles') - .add(toUserProfileDto(userProfile: userProfile)) - .then((value) => true) - .catchError( - (e) => false, - ); + .add(toUserProfileDto(userProfile: userProfile)); } catch (e) { - throw Exception(e); + _exceptionHandling(e); } } @override Future getUserProfile({String? email}) async { - email = email ?? _firebaseService.firebaseAuth.currentUser!.email; + try { + email = email ?? _firebaseService.firebaseAuth.currentUser!.email; - QuerySnapshot> snapshot = await _firestore - .collection('user_profiles') - .where('email', isEqualTo: email) - .get(); + QuerySnapshot> snapshot = await _firestore + .collection('user_profiles') + .where('email', isEqualTo: email) + .get(); - if (snapshot.docs.isEmpty) { - throw Exception('유저 프로필이 존재하지 않습니다.'); + return toUserProfile(json: snapshot.docs[0].data()); + } catch (e) { + throw _exceptionHandling(e); } - - return toUserProfile(json: snapshot.docs[0].data()); } @override - Future updateUserProfile({ + Future updateUserProfile({ required Transaction transaction, required UserProfile userProfile, }) async { @@ -64,15 +64,13 @@ class RemoteUserProfileDataSourceImpl implements RemoteUserProfileDataSource { final originProfileDocRef = originProfileQuery.docs[0].reference; transaction.set( originProfileDocRef, toUserProfileDto(userProfile: userProfile)); - - return true; } catch (e) { - throw Exception(e); + _exceptionHandling(e); } } @override - Future removeUserProfile({String? email}) async { + Future removeUserProfile({String? email}) async { try { email = email ?? _firebaseService.firebaseAuth.currentUser!.email; @@ -81,16 +79,26 @@ class RemoteUserProfileDataSourceImpl implements RemoteUserProfileDataSource { .where('email', isEqualTo: email) .get(); - return await _firestore + await _firestore .collection('user_profiles') .doc(originProfileDocument.docs[0].reference.id) - .delete() - .then((value) => true) - .catchError( - (e) => false, - ); + .update({'deleted_at': Timestamp.now()}); } catch (e) { - throw Exception(e); + _exceptionHandling(e); + } + } + + Exception _exceptionHandling(Object e) { + switch (e.runtimeType) { + case FirebaseException _: + return InternalServerException( + code: ExceptionCode.internalServerException, message: '서버 내부 오류'); + case DioException _: + return NetworkException( + code: ExceptionCode.internalServerException, + message: '네트워크 오류 : $e'); + default: + return Exception(e); } } } diff --git a/lib/data/user/data_source/user_auth_data_source.dart b/lib/data/user/data_source/user_auth_data_source.dart index f3a65f59..869d3ce0 100644 --- a/lib/data/user/data_source/user_auth_data_source.dart +++ b/lib/data/user/data_source/user_auth_data_source.dart @@ -1,21 +1,21 @@ abstract interface class UserAuthDataSource { // 회원가입 - Future signUp({ + Future signUp({ required String email, required String password, }); // 로그인 - Future signIn({ + Future signIn({ required String email, required String password, }); // 로그아웃 - Future logOut(); + Future logOut(); // 회원탈퇴 - Future signOut(); + Future signOut(); // 로그인 체크 email 반환 String? signInCheck(); diff --git a/lib/data/user/repository/user_auth_repository_impl.dart b/lib/data/user/repository/user_auth_repository_impl.dart index c7fda9ca..c98a90d8 100644 --- a/lib/data/user/repository/user_auth_repository_impl.dart +++ b/lib/data/user/repository/user_auth_repository_impl.dart @@ -26,42 +26,35 @@ class UserAuthRepositoryImpl implements UserAuthRepository { /// /// 두 작업이 완료시 return true @override - Future signUp({ + Future signUp({ required UserAuth userAuth, required UserProfile userProfile, }) async { - final signUpResult = await _userAuthDataSource.signUp( + await _userAuthDataSource.signUp( email: userAuth.email, password: userAuth.password); - - if (signUpResult == false) { - return false; - } - - final saveUserProfileResult = await _remoteUserProfileDataSource - .saveUserProfile(userProfile: userProfile); - - if (saveUserProfileResult == false) { + try { + await _remoteUserProfileDataSource.saveUserProfile( + userProfile: userProfile); + } catch (e) { await _userAuthDataSource.signOut(); - return false; + rethrow; } - - return true; } @override - Future signIn({required UserAuth userAuth}) async { - return await _userAuthDataSource.signIn( + Future signIn({required UserAuth userAuth}) async { + await _userAuthDataSource.signIn( email: userAuth.email, password: userAuth.password); } @override - Future logOut() async { - return await _userAuthDataSource.logOut(); + Future logOut() async { + await _userAuthDataSource.logOut(); } @override - Future signOut() async { - return await _userAuthDataSource.signOut(); + Future signOut() async { + await _userAuthDataSource.signOut(); } @override diff --git a/lib/data/weather/data_source/local_data_source/local_daily_location_weather_data_source_impl.dart b/lib/data/weather/data_source/local_data_source/local_daily_location_weather_data_source_impl.dart index 32b92204..18695527 100644 --- a/lib/data/weather/data_source/local_data_source/local_daily_location_weather_data_source_impl.dart +++ b/lib/data/weather/data_source/local_data_source/local_daily_location_weather_data_source_impl.dart @@ -1,5 +1,6 @@ import 'dart:convert'; +import 'package:weaco/core/enum/exception_code.dart'; import 'package:weaco/core/hive/hive_wrapper.dart'; import 'package:weaco/data/weather/data_source/local_data_source/local_daily_location_weather_data_source.dart'; import 'package:weaco/domain/weather/model/daily_location_weather.dart'; @@ -26,9 +27,13 @@ class LocalDailyLocationWeatherDataSourceImpl /// 로컬의 DailyLocationWeather 데이터를 가져와서 반환한다. @override - Future getLocalDailyLocationWeather() async { - final data = await _hiveWrapper.readData(dailyLocationWeatherKey); - if (data == null) return null; - return DailyLocationWeather.fromJson(jsonDecode(data)); + Future getLocalDailyLocationWeather() async { + try { + final data = await _hiveWrapper.readData(dailyLocationWeatherKey); + + return DailyLocationWeather.fromJson(jsonDecode(data!)); + } catch (e) { + throw ExceptionCode.notFoundException; + } } } diff --git a/lib/data/weather/data_source/remote_data_source/meteo_weather_api.dart b/lib/data/weather/data_source/remote_data_source/meteo_weather_api.dart index d34cb4fc..610deec5 100644 --- a/lib/data/weather/data_source/remote_data_source/meteo_weather_api.dart +++ b/lib/data/weather/data_source/remote_data_source/meteo_weather_api.dart @@ -3,7 +3,7 @@ import 'dart:developer'; import 'package:weaco/core/config/meteo_config.dart'; import 'package:weaco/core/dio/base_dio.dart'; import 'package:weaco/core/dio/base_response.dart'; -import 'package:weaco/data/common/http/status_code_handler.dart'; +import 'package:weaco/core/enum/exception_code.dart'; import 'package:weaco/data/weather/data_source/remote_data_source/remote_weather_data_source.dart'; import 'package:weaco/data/weather/dto/weather_dto.dart'; @@ -16,19 +16,27 @@ class MeteoWeatherApi implements RemoteWeatherDataSource { /// @param lat: 위도 /// @param lng: 경도 @override - Future getWeather( - {required double lat, required double lng}) async { - final BaseResponse response = await _dio.get( - path: '${MeteoConfig.baseUrl}/v1/forecast?hourly=temperature_2m,' - 'weathercode&latitude=$lat&longitude=$lng&lang=ko&past_days=1&' - 'forecast_days=2&daily=temperature_2m_max,temperature_2m_min&' - 'timezone=Asia%2FTokyo'); + Future getWeather({ + required double lat, + required double lng, + }) async { + try { + final BaseResponse response = await _dio.get( + path: '${MeteoConfig.baseUrl}/v1/forecast?hourly=temperature_2m,' + 'weathercode&latitude=$lat&longitude=$lng&lang=ko&past_days=1&' + 'forecast_days=2&daily=temperature_2m_max,temperature_2m_min&' + 'timezone=Asia%2FTokyo'); - if (response.statusCode != 200) { - log('Code: ${response.statusCode}, Body: ${response.body}'); - - throw statusCodeHandler(code: response.statusCode); + if (response.statusCode != 200) { + log('Code: ${response.statusCode}, Body: ${response.body}'); + throw ExceptionCode.fromStatus(response.statusCode.toString()); + // throw InternalServerException(code: ExceptionCode.internalServerException, message: 'sdf'); + } + return WeatherDto.fromJson(json: response.body); + } on ExceptionCode catch (_) { + rethrow; + } catch (e) { + throw ExceptionCode.unknownException; } - return WeatherDto.fromJson(json: response.body); } } diff --git a/lib/data/weather/data_source/remote_data_source/remote_weather_background_image_data_source_impl.dart b/lib/data/weather/data_source/remote_data_source/remote_weather_background_image_data_source_impl.dart index f777137d..b46d52fd 100644 --- a/lib/data/weather/data_source/remote_data_source/remote_weather_background_image_data_source_impl.dart +++ b/lib/data/weather/data_source/remote_data_source/remote_weather_background_image_data_source_impl.dart @@ -1,4 +1,6 @@ import 'package:cloud_firestore/cloud_firestore.dart'; +import 'package:dio/dio.dart'; +import 'package:weaco/core/enum/exception_code.dart'; import 'package:weaco/data/weather/data_source/remote_data_source/remote_weather_background_image_data_source.dart'; import 'package:weaco/domain/weather/model/weather_background_image.dart'; @@ -12,11 +14,19 @@ class RemoteWeatherBackgroundImageDataSourceImpl @override Future> getWeatherBackgroundImageList() async { - QuerySnapshot> result = - await _firestore.collection('weather_background_images').get(); - return result.docs - .map((e) => WeatherBackgroundImage( - code: e.data()['code'], imagePath: e.data()['image_path'])) - .toList(); + try { + QuerySnapshot> result = + await _firestore.collection('weather_background_images').get(); + return result.docs + .map((e) => WeatherBackgroundImage( + code: e.data()['code'], imagePath: e.data()['image_path'])) + .toList(); + } catch (e) { + throw switch (e) { + FirebaseException _ => ExceptionCode.internalServerException, + DioException _ => ExceptionCode.internalServerException, + _ => ExceptionCode.unknownException, + }; + } } } diff --git a/lib/data/weather/repository/daily_location_weather_repository_impl.dart b/lib/data/weather/repository/daily_location_weather_repository_impl.dart index 253d35b5..746be497 100644 --- a/lib/data/weather/repository/daily_location_weather_repository_impl.dart +++ b/lib/data/weather/repository/daily_location_weather_repository_impl.dart @@ -1,5 +1,6 @@ import 'dart:developer'; +import 'package:weaco/core/exception/not_found_exception.dart'; import 'package:weaco/data/weather/data_source/remote_data_source/remote_weather_data_source.dart'; import 'package:weaco/data/weather/dto/weather_dto.dart'; import 'package:weaco/data/weather/mapper/daily_location_weather_mapper.dart'; @@ -33,6 +34,10 @@ class DailyLocationWeatherRepositoryImpl await _localDailyLocationWeatherDataSource .getLocalDailyLocationWeather(); + if (localData is NotFoundException) { + await _fetchAndCacheDailyLocationWeather(); + } + return _isOldDataOrExpired(localData) ? await _fetchAndCacheDailyLocationWeather() : localData!; diff --git a/lib/domain/feed/repository/feed_repository.dart b/lib/domain/feed/repository/feed_repository.dart index 2aee6428..70986703 100644 --- a/lib/domain/feed/repository/feed_repository.dart +++ b/lib/domain/feed/repository/feed_repository.dart @@ -11,7 +11,7 @@ abstract interface class FeedRepository { }); /// 피드의 상세 정보를 가져옵니다. - Future getFeed({required String id}); + Future getFeed({required String id}); /// [홈 하단] /// 추천 OOTD 목록을 불러옵니다. diff --git a/lib/domain/feed/repository/ootd_feed_repository.dart b/lib/domain/feed/repository/ootd_feed_repository.dart index bec94879..5024b3da 100644 --- a/lib/domain/feed/repository/ootd_feed_repository.dart +++ b/lib/domain/feed/repository/ootd_feed_repository.dart @@ -1,7 +1,7 @@ import 'package:weaco/domain/feed/model/feed.dart'; abstract interface class OotdFeedRepository { - Future saveOotdFeed({required Feed feed}); + Future saveOotdFeed({required Feed feed}); - Future removeOotdFeed({required String id}); + Future removeOotdFeed({required String id}); } \ No newline at end of file diff --git a/lib/domain/feed/use_case/remove_my_page_feed_use_case.dart b/lib/domain/feed/use_case/remove_my_page_feed_use_case.dart index ae5b1c85..6c5b23df 100644 --- a/lib/domain/feed/use_case/remove_my_page_feed_use_case.dart +++ b/lib/domain/feed/use_case/remove_my_page_feed_use_case.dart @@ -9,7 +9,7 @@ class RemoveMyPageFeedUseCase { /// id를 통해 특정 피드를 삭제 /// @param id: 삭제할 피드의 id /// @return: null - Future execute({required String id}) async { - return await _ootdFeedRepository.removeOotdFeed(id: id); + Future execute({required String id}) async { + await _ootdFeedRepository.removeOotdFeed(id: id); } } diff --git a/lib/domain/feed/use_case/save_edit_feed_use_case.dart b/lib/domain/feed/use_case/save_edit_feed_use_case.dart index df409d02..fa6ea300 100644 --- a/lib/domain/feed/use_case/save_edit_feed_use_case.dart +++ b/lib/domain/feed/use_case/save_edit_feed_use_case.dart @@ -10,7 +10,7 @@ class SaveEditFeedUseCase { /// 특정 피드 저장 또는 업데이트 /// @param feed: 저장할 피드 /// @return: 서버 응답 메세지. response 모델로 변경 예정. - Future execute({required Feed feed}) async { - return await _ootdFeedRepository.saveOotdFeed(feed: feed); + Future execute({required Feed feed}) async { + await _ootdFeedRepository.saveOotdFeed(feed: feed); } } diff --git a/lib/domain/file/repository/file_repository.dart b/lib/domain/file/repository/file_repository.dart index 1e6537c2..d33f53cf 100644 --- a/lib/domain/file/repository/file_repository.dart +++ b/lib/domain/file/repository/file_repository.dart @@ -3,9 +3,9 @@ import 'dart:io'; import 'package:weaco/core/enum/image_type.dart'; abstract interface class FileRepository { - Future getImage({required ImageType imageType}); + Future getImage({required ImageType imageType}); - Future saveImage({required bool isOrigin, required File file, required List compressedImage}); + Future saveImage({required bool isOrigin, required File file, required List compressedImage}); Future> saveOotdImage(); } diff --git a/lib/domain/file/use_case/save_image_use_case.dart b/lib/domain/file/use_case/save_image_use_case.dart index 0c6c3a6a..eecd11e6 100644 --- a/lib/domain/file/use_case/save_image_use_case.dart +++ b/lib/domain/file/use_case/save_image_use_case.dart @@ -16,8 +16,8 @@ class SaveImageUseCase { /// @param isOrigin: 원본 이미지 = true, 크롭된 이미지 = false /// @param file: 저장할 이미지 데이터 /// @return: 데이터 저장 성공 여부 반환 - Future execute({required bool isOrigin, required File file}) async { + Future execute({required bool isOrigin, required File file}) async { final List compressedImage = await _imageCompressor.compressImage(file: file); - return await _fileRepository.saveImage(isOrigin: isOrigin, file: file, compressedImage: compressedImage); + await _fileRepository.saveImage(isOrigin: isOrigin, file: file, compressedImage: compressedImage); } } diff --git a/lib/domain/user/repository/user_auth_repository.dart b/lib/domain/user/repository/user_auth_repository.dart index 212391ab..c485438d 100644 --- a/lib/domain/user/repository/user_auth_repository.dart +++ b/lib/domain/user/repository/user_auth_repository.dart @@ -2,16 +2,16 @@ import 'package:weaco/domain/user/model/user_auth.dart'; import 'package:weaco/domain/user/model/user_profile.dart'; abstract interface class UserAuthRepository { - Future signIn({required UserAuth userAuth}); + Future signIn({required UserAuth userAuth}); - Future signUp({ + Future signUp({ required UserAuth userAuth, required UserProfile userProfile, }); - Future signOut(); + Future signOut(); - Future logOut(); + Future logOut(); String? signInCheck(); } diff --git a/lib/domain/user/use_case/log_out_use_case.dart b/lib/domain/user/use_case/log_out_use_case.dart index 7c411dcc..3fa89b0f 100644 --- a/lib/domain/user/use_case/log_out_use_case.dart +++ b/lib/domain/user/use_case/log_out_use_case.dart @@ -7,7 +7,7 @@ class LogOutUseCase { required UserAuthRepository userAuthRepository, }) : _userAuthRepository = userAuthRepository; - Future execute() async { - return await _userAuthRepository.logOut(); + Future execute() async { + await _userAuthRepository.logOut(); } } diff --git a/lib/domain/user/use_case/sign_in_use_case.dart b/lib/domain/user/use_case/sign_in_use_case.dart index 49e6b658..0283201d 100644 --- a/lib/domain/user/use_case/sign_in_use_case.dart +++ b/lib/domain/user/use_case/sign_in_use_case.dart @@ -9,7 +9,7 @@ class SignInUseCase { }) : _userAuthRepository = userAuthRepository; /// 로그인 - Future execute({required UserAuth userAuth}) async { - return await _userAuthRepository.signIn(userAuth: userAuth); + Future execute({required UserAuth userAuth}) async { + await _userAuthRepository.signIn(userAuth: userAuth); } } diff --git a/lib/domain/user/use_case/sign_out_use_case.dart b/lib/domain/user/use_case/sign_out_use_case.dart index 07fd7a4e..08c45e97 100644 --- a/lib/domain/user/use_case/sign_out_use_case.dart +++ b/lib/domain/user/use_case/sign_out_use_case.dart @@ -8,7 +8,7 @@ class SignOutUseCase { }) : _userAuthRepository = userAuthRepository; /// 설정 화면의 회월 탈퇴를 위한 Use Case - Future execute() async { - return await _userAuthRepository.signOut(); + Future execute() async { + await _userAuthRepository.signOut(); } } diff --git a/lib/domain/user/use_case/sign_up_use_case.dart b/lib/domain/user/use_case/sign_up_use_case.dart index 1d8770a6..7966b07a 100644 --- a/lib/domain/user/use_case/sign_up_use_case.dart +++ b/lib/domain/user/use_case/sign_up_use_case.dart @@ -13,14 +13,10 @@ class SignUpUseCase { /// [userAuth] : 회원 가입을 위한 이메일, 비밀번호 정보 /// [userProfile] : 회원 가입을 위한 프로필 정보 /// 회원 가입 성공시 true 반환, 실패시 false 반환 - Future execute( + Future execute( {required UserAuth userAuth, required UserProfile userProfile}) async { - final bool result = await _userAuthRepository.signUp( + await _userAuthRepository.signUp( userAuth: userAuth, userProfile: userProfile); - if (result) { - await _userAuthRepository.signIn(userAuth: userAuth); - } - - return result; + await _userAuthRepository.signIn(userAuth: userAuth); } } diff --git a/lib/presentation/my_page/screen/my_page_screen.dart b/lib/presentation/my_page/screen/my_page_screen.dart index 22955ed6..d1908734 100644 --- a/lib/presentation/my_page/screen/my_page_screen.dart +++ b/lib/presentation/my_page/screen/my_page_screen.dart @@ -201,19 +201,11 @@ class _MyPageScreenState extends State { myPageViewModel .removeSelectedFeed(currentFeed.id!) .then((result) { - if (result) { - AlertUtil.showAlert( - context: context, - exceptionAlert: ExceptionAlert.snackBar, - message: '피드가 삭제 되었습니다.', - ); - } else { - AlertUtil.showAlert( - context: context, - exceptionAlert: ExceptionAlert.snackBar, - message: '피드가 삭제에 실패했습니다.', - ); - } + AlertUtil.showAlert( + context: context, + exceptionAlert: ExceptionAlert.snackBar, + message: '피드가 삭제 되었습니다.', + ); context.pop(); context.pop(); diff --git a/lib/presentation/my_page/view_model/my_page_view_model.dart b/lib/presentation/my_page/view_model/my_page_view_model.dart index 09425195..55d80cc6 100644 --- a/lib/presentation/my_page/view_model/my_page_view_model.dart +++ b/lib/presentation/my_page/view_model/my_page_view_model.dart @@ -1,6 +1,7 @@ import 'dart:developer'; import 'package:flutter/widgets.dart'; +import 'package:weaco/core/enum/exception_code.dart'; import 'package:weaco/core/exception/not_found_exception.dart'; import 'package:weaco/domain/feed/model/feed.dart'; import 'package:weaco/domain/feed/use_case/get_my_page_feeds_use_case.dart'; @@ -83,7 +84,7 @@ class MyPageViewModel with ChangeNotifier { (result) { if (result == null) { throw NotFoundException( - code: 404, + code: ExceptionCode.notFoundException, message: '이메일과 일치하는 사용자가 없습니다.', ); } @@ -150,21 +151,16 @@ class MyPageViewModel with ChangeNotifier { } // Feed 리스트에서 특정 피드 삭제 - Future removeSelectedFeed(String feedId) async { + Future removeSelectedFeed(String feedId) async { try { - final result = await _removeMyPageFeedUseCase.execute(id: feedId); + await _removeMyPageFeedUseCase.execute(id: feedId); - if (result) { - _decreaseFeedCount(); - _removeFeedFromList(feedId); - } + _decreaseFeedCount(); + _removeFeedFromList(feedId); notifyListeners(); - - return result; } on Exception catch (e) { log(e.toString(), name: 'MyPageViewModel.removeSelectedFeed()'); - return false; } } diff --git a/lib/presentation/ootd_post/screen/ootd_post_screen.dart b/lib/presentation/ootd_post/screen/ootd_post_screen.dart index 2e1bb442..c40a6f3e 100644 --- a/lib/presentation/ootd_post/screen/ootd_post_screen.dart +++ b/lib/presentation/ootd_post/screen/ootd_post_screen.dart @@ -228,15 +228,7 @@ class _OotdPostScreenState extends State { } if (mounted) { - if (viewModel.saveStatus) { - RouterStatic.goToDefault(context); - } else { - AlertUtil.showAlert( - context: context, - exceptionAlert: ExceptionAlert.snackBar, - message: '다시 시도해 주세요.', - ); - } + RouterStatic.goToDefault(context); } }, child: viewModel.showSpinner diff --git a/lib/presentation/ootd_post/view_model/ootd_post_view_model.dart b/lib/presentation/ootd_post/view_model/ootd_post_view_model.dart index 1064a3eb..3ad9bd8e 100644 --- a/lib/presentation/ootd_post/view_model/ootd_post_view_model.dart +++ b/lib/presentation/ootd_post/view_model/ootd_post_view_model.dart @@ -16,7 +16,6 @@ class OotdPostViewModel with ChangeNotifier { final GetDailyLocationWeatherUseCase _getDailyLocationWeatherUseCase; final SaveEditFeedUseCase _saveEditFeedUseCase; bool _showSpinner = false; - bool _saveStatus = false; File? _originImage; File? _croppedImage; Weather? _weather; @@ -38,7 +37,8 @@ class OotdPostViewModel with ChangeNotifier { notifyListeners(); try { - _croppedImage = await _getImageUseCase.execute(imageType: ImageType.cropped); + _croppedImage = + await _getImageUseCase.execute(imageType: ImageType.cropped); _dailyLocationWeather = await _getDailyLocationWeatherUseCase.execute(); // 현재 시간 날씨 _weather = _dailyLocationWeather!.weatherList.firstWhere((element) { @@ -79,7 +79,7 @@ class OotdPostViewModel with ChangeNotifier { createdAt: now, ); - _saveStatus = await _saveEditFeedUseCase.execute(feed: feed); + await _saveEditFeedUseCase.execute(feed: feed); _showSpinner = false; notifyListeners(); @@ -101,7 +101,7 @@ class OotdPostViewModel with ChangeNotifier { createdAt: feed.createdAt, ); - _saveStatus = await _saveEditFeedUseCase.execute(feed: editedFeed); + await _saveEditFeedUseCase.execute(feed: editedFeed); _showSpinner = false; notifyListeners(); @@ -120,7 +120,5 @@ class OotdPostViewModel with ChangeNotifier { DailyLocationWeather? get dailyLocationWeather => _dailyLocationWeather; - bool get saveStatus => _saveStatus; - bool get showSpinner => _showSpinner; } diff --git a/lib/presentation/ootd_post/view_model/picutre_crop_view_model.dart b/lib/presentation/ootd_post/view_model/picutre_crop_view_model.dart index c1814a00..203dcae6 100644 --- a/lib/presentation/ootd_post/view_model/picutre_crop_view_model.dart +++ b/lib/presentation/ootd_post/view_model/picutre_crop_view_model.dart @@ -17,7 +17,7 @@ enum PictureCropSaveStatus { class PictureCropViewModel with ChangeNotifier { final SaveImageUseCase _saveImageUseCase; - PictureCropSaveStatus _status = PictureCropSaveStatus.idle; + final PictureCropSaveStatus _status = PictureCropSaveStatus.idle; PictureCropViewModel({ required SaveImageUseCase saveImageUseCase, @@ -30,14 +30,8 @@ class PictureCropViewModel with ChangeNotifier { /// 크롭 이미지 저장 Future saveCroppedImage({required File file}) async { - final bool result = - await _saveImageUseCase.execute(isOrigin: false, file: file); - - if (result) { - _status = PictureCropSaveStatus.success; - } else { - _status = PictureCropSaveStatus.error; - } + await _saveImageUseCase.execute(isOrigin: false, file: file); + notifyListeners(); } diff --git a/lib/presentation/settings/screen/app_setting_screen.dart b/lib/presentation/settings/screen/app_setting_screen.dart index b1ada6bf..a128d337 100644 --- a/lib/presentation/settings/screen/app_setting_screen.dart +++ b/lib/presentation/settings/screen/app_setting_screen.dart @@ -113,21 +113,14 @@ class _AppSettingScreenState extends State { context.pop(); context.read().logOut().then((value) { - if (value) { - context.read().signOut(); + context.read().signOut(); - AlertUtil.showAlert( - context: context, - exceptionAlert: ExceptionAlert.snackBar, - message: '로그아웃에 성공했습니다.'); + AlertUtil.showAlert( + context: context, + exceptionAlert: ExceptionAlert.snackBar, + message: '로그아웃에 성공했습니다.'); - RouterStatic.clearAndNavigate(context, RouterPath.defaultPage.path); - } else { - AlertUtil.showAlert( - context: context, - exceptionAlert: ExceptionAlert.snackBar, - message: '로그아웃에 실패했습니다.'); - } + RouterStatic.clearAndNavigate(context, RouterPath.defaultPage.path); }); } @@ -135,21 +128,14 @@ class _AppSettingScreenState extends State { context.pop(); context.read().signOut().then((value) { - if (value) { - context.read().signOut(); + context.read().signOut(); - AlertUtil.showAlert( - context: context, - exceptionAlert: ExceptionAlert.snackBar, - message: '회원탈퇴에 성공했습니다.'); + AlertUtil.showAlert( + context: context, + exceptionAlert: ExceptionAlert.snackBar, + message: '회원탈퇴에 성공했습니다.'); - RouterStatic.clearAndNavigate(context, RouterPath.defaultPage.path); - } else { - AlertUtil.showAlert( - context: context, - exceptionAlert: ExceptionAlert.snackBar, - message: '회원탈퇴에 실패했습니다.'); - } + RouterStatic.clearAndNavigate(context, RouterPath.defaultPage.path); }); } } diff --git a/lib/presentation/settings/view_model/app_setting_view_model.dart b/lib/presentation/settings/view_model/app_setting_view_model.dart index b32dd8b3..7ebb8098 100644 --- a/lib/presentation/settings/view_model/app_setting_view_model.dart +++ b/lib/presentation/settings/view_model/app_setting_view_model.dart @@ -37,20 +37,12 @@ class AppSettingViewModel with ChangeNotifier { } /// 로그아웃 성공 시, true 반환 - Future logOut() async { - try { - return await _logOutUseCase.execute(); - } catch (e) { - return false; - } + Future logOut() async { + return await _logOutUseCase.execute(); } /// 회원탈퇴 성공 시, true 반환 - Future signOut() async { - try { - return await _signOutUseCase.execute(); - } catch (e) { - return false; - } + Future signOut() async { + return await _signOutUseCase.execute(); } } diff --git a/lib/presentation/user_page/view_model/user_page_view_model.dart b/lib/presentation/user_page/view_model/user_page_view_model.dart index baa1e0d9..ff5ea7ae 100644 --- a/lib/presentation/user_page/view_model/user_page_view_model.dart +++ b/lib/presentation/user_page/view_model/user_page_view_model.dart @@ -1,6 +1,7 @@ import 'dart:developer'; import 'package:flutter/widgets.dart'; +import 'package:weaco/core/enum/exception_code.dart'; import 'package:weaco/core/exception/not_found_exception.dart'; import 'package:weaco/domain/feed/model/feed.dart'; import 'package:weaco/domain/feed/use_case/get_user_page_feeds_use_case.dart'; @@ -87,7 +88,7 @@ class UserPageViewModel with ChangeNotifier { if (result == null) { throw NotFoundException( - code: 404, + code: ExceptionCode.notFoundException, message: '이메일과 일치하는 사용자가 없습니다.', ); } diff --git a/test/data/feed/data_source/remote_feed_data_source_impl_test.dart b/test/data/feed/data_source/remote_feed_data_source_impl_test.dart index 5156c097..60ee1b69 100644 --- a/test/data/feed/data_source/remote_feed_data_source_impl_test.dart +++ b/test/data/feed/data_source/remote_feed_data_source_impl_test.dart @@ -24,7 +24,7 @@ void main() { group( 'saveFeed()는', () { - test('Firestore에 Feed를 저장하고, true를 반환해야 한다', () async { + test('Firestore에 Feed를 저장 요청을 보낸다.', () async { // Given Weather mockWeather = Weather( temperature: 31, @@ -51,17 +51,18 @@ void main() { ); // When - final result = - await fakeFirestore.runTransaction((transaction) async { + await fakeFirestore.runTransaction((transaction) async { return await dataSource.saveFeed( transaction: transaction, feed: mockFeed, ); }); - + final snapshot = + await fakeFirestore.collection('feeds').doc(mockFeed.id).get(); // Then - expect(result, true); + expect(mockFeed.userEmail, snapshot['user_email']); }); + test( 'Firestore에 데이터를 추가해야 한다.', () async { @@ -196,7 +197,7 @@ void main() { }); }); group('deletedFeed()는', () { - test('id값을 전달하면, 특정 Feed를 삭제하고 true를 반환해야 한다', () async { + test('id값을 전달하면, 특정 Feed를 삭제 요청을 한다.', () async { // Given const testId = 'testId'; @@ -227,8 +228,7 @@ void main() { }); // When - final result = - await fakeFirestore.runTransaction((transaction) async { + await fakeFirestore.runTransaction((transaction) async { return await dataSource.deleteFeed( transaction: transaction, id: testId, @@ -241,7 +241,7 @@ void main() { toFeed(json: docResult.data()!, id: docResult.id).deletedAt; // Then - expect(result, feedDeletedAt != null); + expect(feedDeletedAt != null, true); }); }); group('getSearchFeedList()는', () { diff --git a/test/data/feed/repository/ootd_feed_repository_impl_test.dart b/test/data/feed/repository/ootd_feed_repository_impl_test.dart index 518a063d..21f70812 100644 --- a/test/data/feed/repository/ootd_feed_repository_impl_test.dart +++ b/test/data/feed/repository/ootd_feed_repository_impl_test.dart @@ -50,7 +50,7 @@ void main() { ); final mockUserProfile = UserProfile( - email: 'email', + email: 'test@email.com', nickname: 'nickname', gender: 1, profileImagePath: 'profileImagePath', @@ -62,7 +62,6 @@ void main() { fileRepository.initMockData(); remoteFeedDataSource.cleanUpMockData(); remoteUserProfileDatSource.initMockData(); - remoteUserProfileDatSource.getUserProfileResult = mockUserProfile; }); @@ -151,19 +150,6 @@ void main() { expectedUseProfile); }); - test( - 'RemoteFeedDataSourceImpl.saveFeed, RemoteUserProfileDataSourceImpl.updateUserProfile()를 ' - '정상적으로 호출한 뒤, true 를 반환한다.', () async { - // Given - const expected = true; - - // When - final actual = await ootdFeedRepository.saveOotdFeed(feed: mockFeed); - - // Then - expect(actual, expected); - }); - test( '파라미터로 전달받은 Feed의 id값이 있으면 수정하는 Feed로써' 'RemoteFeedDataSourceImpl.saveFeed()를 한번 호출한다.', () async { @@ -255,25 +241,13 @@ void main() { mockUserProfile.copyWith(feedCount: mockUserProfile.feedCount - 1); // When + // remove 메소드에 run transaction에 await 없었음 await ootdFeedRepository.removeOotdFeed(id: feedId); // Then expect(remoteUserProfileDatSource.methodUserProfileParameter, expectedUserProfile); }); - - test( - 'RemoteFeedDataSourceImpl.deleteFeed(), OotdFeedRepositoryImpl.updateMyFeedCount()를 ' - '정상적으로 호출한 뒤, true 를 반환한다.', () async { - // Given - const expected = true; - - // When - final actual = await ootdFeedRepository.removeOotdFeed(id: feedId); - - // Then - expect(actual, expected); - }); }); }); } diff --git a/test/data/file/data_source/local_file_data_source_test.dart b/test/data/file/data_source/local_file_data_source_test.dart index 779a5472..87426d2a 100644 --- a/test/data/file/data_source/local_file_data_source_test.dart +++ b/test/data/file/data_source/local_file_data_source_test.dart @@ -1,5 +1,6 @@ import 'dart:io'; import 'package:flutter_test/flutter_test.dart'; +import 'package:weaco/core/enum/exception_code.dart'; import 'package:weaco/core/enum/image_type.dart'; import 'package:weaco/core/path_provider/path_provider_service.dart'; import 'package:weaco/data/file/data_source/local/local_file_data_source.dart'; @@ -14,8 +15,8 @@ void main() { final LocalFileDataSource dataSource = LocalFileDataSourceImpl(pathProvider: mockPathProvider); - group('getImagePath 메서드는', () { - tearDown(() { + group('getImage 메서드는', () { + setUp(() { if (File('test/mock/assets/origin.png').existsSync()) { File('test/mock/assets/origin.png').deleteSync(); } @@ -35,7 +36,7 @@ void main() { File? file = await dataSource.getImage(imageType: imageType); // Then - expect(file?.readAsBytesSync(), + expect(file.readAsBytesSync(), File('test/mock/assets/origin.png').readAsBytesSync()); }); @@ -49,19 +50,16 @@ void main() { File? file = await dataSource.getImage(imageType: imageType); // Then - expect(file?.readAsBytesSync(), + expect(file.readAsBytesSync(), File('test/mock/assets/cropped.png').readAsBytesSync()); }); - test('찾으려는 파일이 없는 경우, null을 반환한다.', () async { + test('찾으려는 파일이 없는 경우, ExceptionCode.notFoundException 예외를 던진다.', () async { // Given const imageType = ImageType.cropped; - // When - File? file = await dataSource.getImage(imageType: imageType); - - // Then - expect(file, null); + // When, Then + expect(dataSource.getImage(imageType: imageType), throwsA(ExceptionCode.notFoundException)); }); }); diff --git a/test/data/file/data_source/remote_file_data_source_test.dart b/test/data/file/data_source/remote_file_data_source_test.dart index 56c3b561..abc921a7 100644 --- a/test/data/file/data_source/remote_file_data_source_test.dart +++ b/test/data/file/data_source/remote_file_data_source_test.dart @@ -45,14 +45,12 @@ void main() { File? croppedImage = await localFileDataSource.getImage(imageType: ImageType.cropped); File? compressedImage = await localFileDataSource.getImage(imageType: ImageType.compressed); - if (croppedImage != null && compressedImage != null) { - final path = - await remoteFileDataSource.saveImage(croppedImage: croppedImage, compressedImage: compressedImage); - - expect(path[0].startsWith('${bucketPath}feed_origin_images/$email'), true); - expect(path[1].startsWith('${bucketPath}feed_thumbnail_images/$email'), true); - } - }); + final path = + await remoteFileDataSource.saveImage(croppedImage: croppedImage, compressedImage: compressedImage); + + expect(path[0].startsWith('${bucketPath}feed_origin_images/$email'), true); + expect(path[1].startsWith('${bucketPath}feed_thumbnail_images/$email'), true); + }); }); }); } diff --git a/test/data/file/repository/file_repository_impl_test.dart b/test/data/file/repository/file_repository_impl_test.dart index d5ed4b18..bc3aed20 100644 --- a/test/data/file/repository/file_repository_impl_test.dart +++ b/test/data/file/repository/file_repository_impl_test.dart @@ -129,14 +129,6 @@ void main() { expect(mockLocalFileDataSource.methodCallCount['getImage'], 2); }); - test('LocalFileDataSource.getImage()의 반환 값이 null이라면 Exception을 발생시킨다.', () async { - // Given - mockLocalFileDataSource.methodResult['getImage'] = null; - - // When // Then - expect(fileRepository.saveOotdImage(),throwsA(isA())); - }); - test('RemoteFileDataSource.saveImage()의 반환 값을 그대로 반환한다.', () async { // Given const List expectResult = ['test/mock/assets/test_image.png', 'test/mock/assets/test_image.png']; diff --git a/test/data/user/repository/user_auth_repository_impl_test.dart b/test/data/user/repository/user_auth_repository_impl_test.dart index a42b15ac..524628b9 100644 --- a/test/data/user/repository/user_auth_repository_impl_test.dart +++ b/test/data/user/repository/user_auth_repository_impl_test.dart @@ -52,26 +52,6 @@ void main() { expect(userAuthDataSource.signUpCallCount, expectCallCount); }); - test( - 'UserAuthDataSource.signUp() 이 실패하면' - 'RemoteUserProfileDataSource.saveUserProfile() 메소드를' - '호출하지 않는다.', () async { - // given - int expectCallCount = 0; - - userAuthDataSource.returnValue = false; - - // when - await userAuthRepository.signUp( - userAuth: userAuth, - userProfile: userProfile, - ); - - // then - expect(userProfileDataSource.saveUserProfileMethodCallCount, - expectCallCount); - }); - test( 'UserAuthDataSource.signUp() 이 성공하면' 'RemoteUserProfileDataSource.saveUserProfile() 메소드를' @@ -121,171 +101,63 @@ void main() { expectUserProfile); }); - test('회원가입이 성공했을 때 true 를 반환한다.', () async { - // given - final expectUserAuth = userAuth.copyWith(); - final expectUserProfile = userProfile.copyWith(); + group('signIn() 메소드는', () { + test('UserAuthDataSource.signIn() 메소드를 1회 호출한다.', () async { + // given + int expectCallCount = 1; - userAuthDataSource.returnValue = true; - userProfileDataSource.isSaved = true; + // when + await userAuthRepository.signIn( + userAuth: userAuth, + ); - // when - final actualResult = await userAuthRepository.signUp( - userAuth: expectUserAuth, - userProfile: expectUserProfile, - ); + // then + expect(userAuthDataSource.signInCallCount, expectCallCount); + }); - // then - expect(actualResult, true); - }); - test('회원가입이 성공했을 때 false 를 반환한다.', () async { - // given - final expectUserAuth = userAuth.copyWith(); - final expectUserProfile = userProfile.copyWith(); + test('인자로 받은 값을 UserAuthDataSource.signIn() 메소드에 그대로 전달한다.', () async { + // given + final expectUserAuth = userAuth.copyWith(); - userAuthDataSource.returnValue = false; + final expectUserAuthParameter = { + 'email': expectUserAuth.email, + 'password': expectUserAuth.password, + }; - // when - final actualResult = await userAuthRepository.signUp( - userAuth: expectUserAuth, - userProfile: expectUserProfile, - ); + // when + await userAuthRepository.signIn( + userAuth: expectUserAuth, + ); - // then - expect(actualResult, false); + // then + expect(userAuthDataSource.methodParameter, expectUserAuthParameter); + }); }); - }); - group('signIn() 메소드는', () { - test('UserAuthDataSource.signIn() 메소드를 1회 호출한다.', () async { - // given - int expectCallCount = 1; + group('logOut() 메소드는', () { + test('UserAuthDataSource.logOut() 메소드를 1회 호출한다.', () async { + // given + int expectCallCount = 1; - // when - await userAuthRepository.signIn( - userAuth: userAuth, - ); + // when + await userAuthRepository.logOut(); - // then - expect(userAuthDataSource.signInCallCount, expectCallCount); + // then + expect(userAuthDataSource.logOutCallCount, expectCallCount); + }); }); - test('인자로 받은 값을 UserAuthDataSource.signIn() 메소드에 그대로 전달한다.', () async { - // given - final expectUserAuth = userAuth.copyWith(); + group('signOut() 메소드는', () { + test('UserAuthDataSource.signOut() 메소드를 1회 호출한다.', () async { + // given + int expectCallCount = 1; - final expectUserAuthParameter = { - 'email': expectUserAuth.email, - 'password': expectUserAuth.password, - }; + // when + await userAuthRepository.signOut(); - // when - await userAuthRepository.signIn( - userAuth: expectUserAuth, - ); - - // then - expect(userAuthDataSource.methodParameter, expectUserAuthParameter); - }); - - test('로그인이 성공했을 때 true 를 반환한다.', () async { - // given - final expectUserAuth = userAuth.copyWith(); - - userAuthDataSource.returnValue = true; - - // when - final actualResult = await userAuthRepository.signIn( - userAuth: expectUserAuth, - ); - - // then - expect(actualResult, true); - }); - - test('로그인이 성공했을 때 false 를 반환한다.', () async { - // given - final expectUserAuth = userAuth.copyWith(); - - userAuthDataSource.returnValue = false; - - // when - final actualResult = await userAuthRepository.signIn( - userAuth: expectUserAuth, - ); - - // then - expect(actualResult, false); - }); - }); - - group('logOut() 메소드는', () { - test('UserAuthDataSource.logOut() 메소드를 1회 호출한다.', () async { - // given - int expectCallCount = 1; - - // when - await userAuthRepository.logOut(); - - // then - expect(userAuthDataSource.logOutCallCount, expectCallCount); - }); - - test('로그아웃이 성공했을 때 true 를 반환한다.', () async { - // given - userAuthDataSource.returnValue = true; - - // when - final actualResult = await userAuthRepository.logOut(); - - // then - expect(actualResult, true); - }); - - test('로그아웃이 성공했을 때 false 를 반환한다.', () async { - // given - userAuthDataSource.returnValue = false; - - // when - final actualResult = await userAuthRepository.logOut(); - - // then - expect(actualResult, false); - }); - }); - - group('signOut() 메소드는', () { - test('UserAuthDataSource.signOut() 메소드를 1회 호출한다.', () async { - // given - int expectCallCount = 1; - - // when - await userAuthRepository.signOut(); - - // then - expect(userAuthDataSource.signOutCallCount, expectCallCount); - }); - - test('회원탈퇴가 성공했을 때 true 를 반환한다.', () async { - // given - userAuthDataSource.returnValue = true; - - // when - final actualResult = await userAuthRepository.signOut(); - - // then - expect(actualResult, true); - }); - - test('회원탈퇴가 성공했을 때 false 를 반환한다.', () async { - // given - userAuthDataSource.returnValue = false; - - // when - final actualResult = await userAuthRepository.signOut(); - - // then - expect(actualResult, false); + // then + expect(userAuthDataSource.signOutCallCount, expectCallCount); + }); }); }); }); diff --git a/test/data/weather/data_source/remote_data_source/meteo_weather_api_test.dart b/test/data/weather/data_source/remote_data_source/meteo_weather_api_test.dart index 797a4639..e08d1c98 100644 --- a/test/data/weather/data_source/remote_data_source/meteo_weather_api_test.dart +++ b/test/data/weather/data_source/remote_data_source/meteo_weather_api_test.dart @@ -2,8 +2,7 @@ import 'package:flutter_dotenv/flutter_dotenv.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:weaco/core/config/meteo_config.dart'; import 'package:weaco/core/dio/base_response.dart'; -import 'package:weaco/core/exception/internal_server_exception.dart'; -import 'package:weaco/core/exception/not_found_exception.dart'; +import 'package:weaco/core/enum/exception_code.dart'; import 'package:weaco/data/weather/data_source/remote_data_source/meteo_weather_api.dart'; import 'package:weaco/data/weather/dto/daily_dto.dart'; import 'package:weaco/data/weather/dto/hourly_dto.dart'; @@ -39,14 +38,14 @@ Future main() async { expect(mockMeteoDio.getPathParameter, expectedUrl); }); - test('반환받은 status code가 404라면 NotFoundException예외를 던진다.', () async { + test('반환받은 status code가 200이 아니라면 ExceptionCode예외를 던진다.', () async { // Given mockMeteoDio.getResponseReturnData = BaseResponse(statusCode: 404, body: {}); // When Then expect(meteoWeatherApi.getWeather(lat: lat, lng: lng), - throwsA(isA())); + throwsA(ExceptionCode.internalServerException)); }); test('반환받은 status code가 500이라면 InternalServerException예외를 던진다.', @@ -57,7 +56,7 @@ Future main() async { // When Then expect(meteoWeatherApi.getWeather(lat: lat, lng: lng), - throwsA(isA())); + throwsA(ExceptionCode.internalServerException)); }); test('반환받은 status code가 200이라면 BaseResponse를 반환한다.', () async { diff --git a/test/domain/feed/use_case/get_detail_feed_detail_use_case_test.dart b/test/domain/feed/use_case/get_detail_feed_detail_use_case_test.dart index 2795b48d..48739a57 100644 --- a/test/domain/feed/use_case/get_detail_feed_detail_use_case_test.dart +++ b/test/domain/feed/use_case/get_detail_feed_detail_use_case_test.dart @@ -20,6 +20,28 @@ void main() { test('파라미터로 받은 id를 FeedRepository.getFeed에 넘긴다.', () async { // Given const String expectedId = 'id'; + feedRepository.getFeedResult = Feed( + id: 'id', + imagePath: 'imagePath', + thumbnailImagePath: 'thumbnailImagePath', + userEmail: 'userEmail', + description: 'description', + weather: Weather( + temperature: 1, + timeTemperature: DateTime.now(), + code: 1, + createdAt: DateTime.now(), + ), + seasonCode: 1, + location: Location( + lat: 1, + lng: 1, + city: 'city', + createdAt: DateTime.now(), + ), + createdAt: DateTime.now(), + deletedAt: null, + ); // When await getDetailFeedDetailUseCase.execute(id: expectedId); diff --git a/test/domain/feed/use_case/remove_my_page_feed_use_case_test.dart b/test/domain/feed/use_case/remove_my_page_feed_use_case_test.dart index 4df7b726..8fd6881d 100644 --- a/test/domain/feed/use_case/remove_my_page_feed_use_case_test.dart +++ b/test/domain/feed/use_case/remove_my_page_feed_use_case_test.dart @@ -7,11 +7,12 @@ void main() { final mockOotdFeedRepository = MockOotdFeedRepositoryImpl(); final RemoveMyPageFeedUseCase useCase = RemoveMyPageFeedUseCase(ootdFeedRepository: mockOotdFeedRepository); - + setUp(() => mockOotdFeedRepository.initMockData()); group('execute 메소드는', () { test('파라미터로 전달받은 id를 OotdFeedRepository에 그대로 전달한다.', () async { // Given const expected = 'id'; + // mockOotdFeedRepository. // When await useCase.execute(id: expected); @@ -20,16 +21,15 @@ void main() { expect(mockOotdFeedRepository.removeOotdFeedParamId, expected); }); - test('OotdFeedRepository.removeOotdFeed를 호출하고 반환받은 값을 그대로 반환한다.', () async { + test('OotdFeedRepository.removeOotdFeed를 한번 호출한다.', () async { // Given - const expected = true; - mockOotdFeedRepository.removeOotdFeedReturnValue = expected; + const expected = 1; // When - final result = await useCase.execute(id: 'id'); + await useCase.execute(id: 'id'); // Then - expect(result, expected); + expect(mockOotdFeedRepository.removeOotdFeedCallCount, expected); }); }); }); diff --git a/test/domain/feed/use_case/save_edit_feed_use_case_test.dart b/test/domain/feed/use_case/save_edit_feed_use_case_test.dart index bfdcea11..280bfa4f 100644 --- a/test/domain/feed/use_case/save_edit_feed_use_case_test.dart +++ b/test/domain/feed/use_case/save_edit_feed_use_case_test.dart @@ -47,41 +47,6 @@ void main() { // Then expect(ootdFeedRepository.saveOotdFeedCallCount, expectedCallCount); }); - - test('OotdFeedRepository.saveFeed를 호출하고 반환받은 값을 그대로 반환한다.', () async { - // Given - const bool expected = true; - final editedFeed = Feed( - id: 'id', - imagePath: 'imagePath', - thumbnailImagePath: 'thumbnailImagePath', - userEmail: 'userEmail', - description: 'description', - weather: Weather( - temperature: 1, - timeTemperature: DateTime.now(), - code: 1, - createdAt: DateTime.now(), - ), - seasonCode: 1, - location: Location( - lat: 1, - lng: 1, - city: 'city', - createdAt: DateTime.now(), - ), - createdAt: DateTime.now(), - deletedAt: null, - ); - ootdFeedRepository.saveOotdFeedParamFeed = editedFeed; - ootdFeedRepository.saveOotdFeedReturnValue = expected; - - // When - final actual = await saveEditFeedUseCase.execute(feed: editedFeed); - - // Then - expect(actual, expected); - }); }); }); } diff --git a/test/domain/file/use_case/save_image_use_case_test.dart b/test/domain/file/use_case/save_image_use_case_test.dart index 29dd0c19..9e993daf 100644 --- a/test/domain/file/use_case/save_image_use_case_test.dart +++ b/test/domain/file/use_case/save_image_use_case_test.dart @@ -37,20 +37,6 @@ void main() { // Then expect(mockFileRepository.methodParameterMap['data'], data); }); - - test('FileRepository.saveImage()을 호출하고 반환 받은 값을 그대로 반환한다.', () async { - // Given - File data = File('flutter-wea-co\\test\\mock\\assets\\test_file.txt'); - bool expectResult = false; - mockFileRepository.saveImageResult = expectResult; - - // When - final result = - await mockFileRepository.saveImage(isOrigin: true, file: data); - - // Then - expect(result, expectResult); - }); }); }); } diff --git a/test/domain/user/data_source/remote_user_profile_data_source_test.dart b/test/domain/user/data_source/remote_user_profile_data_source_test.dart index 76ca1c37..06293c8e 100644 --- a/test/domain/user/data_source/remote_user_profile_data_source_test.dart +++ b/test/domain/user/data_source/remote_user_profile_data_source_test.dart @@ -33,11 +33,17 @@ void main() async { ); // When - final bool res = - await dataSource.saveUserProfile(userProfile: expectedUserProfile); + await dataSource.saveUserProfile(userProfile: expectedUserProfile); + + final actual = await instance + .collection('user_profiles') + .where('email', isEqualTo: 'test@gmail.com') + .get(); + + final data = actual.docs.first.data()['email']; // Then - expect(res, true); + expect(data, expectedUserProfile.email); }); test( 'getUserProfile()은 firebase storage에서 파라미터로 받은 이메일과 동일한 유저 프로필 정보를 반환한다.', @@ -106,52 +112,15 @@ void main() async { expect(result, expectProfile); }, ); - - test( - 'updateUserProfile()은 userProfile 이 null 일 경우, 현재 유저 프로필 정보를 업데이트한다.', - () async { - // Given - await instance.collection('user_profiles').add({ - 'created_at': '2024-05-01 13:27:00', - 'deleted_at': null, - 'email': 'test@gmail.com', - 'feed_count': 0, - 'gender': 1, - 'nickname': '호구몬', - 'profile_image_path': - 'https://health.chosun.com/site/data/img_dir/2024/01/22/2024012201607_0.jpg' - }); - - final editedUserProfile = UserProfile( - email: 'test@gmail.com', - nickname: '테스트123', - gender: 1, - profileImagePath: - 'https://health.chosun.com/site/data/img_dir/2024/01/22/2024012201607_0.jpg', - feedCount: 0, - createdAt: DateTime.parse('2024-05-01 13:27:00'), - ); - - // When - final res = await instance.runTransaction((transaction) async { - return await dataSource.updateUserProfile( - transaction: transaction, - userProfile: editedUserProfile, - ); - }); - - // Then - expect(res, true); - }, - ); test( 'removeUserProfile()은 firebase storage에서 파라미터로 받은 이메일과 동일한 유저 프로필 정보를 삭제한다.', () async { // Given + const email = 'test@gmail.com'; await instance.collection('user_profiles').add({ 'created_at': '2024-05-01 13:27:00', 'deleted_at': null, - 'email': 'test@gmail.com', + 'email': email, 'feed_count': 0, 'gender': 1, 'nickname': '호구몬', @@ -160,10 +129,16 @@ void main() async { }); // When - final bool res = await dataSource.removeUserProfile(); + await dataSource.removeUserProfile(email: email); + final actual = await instance + .collection('user_profiles') + .where('email', isEqualTo: 'test@gmail.com') + .get(); + + final data = actual.docs.first.data()['deleted_at']; // Then - expect(res, true); + expect(data != null, true); }, ); @@ -183,10 +158,16 @@ void main() async { }); // When - final bool res = await dataSource.removeUserProfile(); + await dataSource.removeUserProfile(); + final actual = await instance + .collection('user_profiles') + .where('email', isEqualTo: firebaseService.user?.email) + .get(); + + final data = actual.docs.first.data()['deleted_at']; // Then - expect(res, true); + expect(data != null, true); }, ); }, diff --git a/test/domain/user/use_case/log_out_use_case_test.dart b/test/domain/user/use_case/log_out_use_case_test.dart index e16cca62..d0690745 100644 --- a/test/domain/user/use_case/log_out_use_case_test.dart +++ b/test/domain/user/use_case/log_out_use_case_test.dart @@ -3,7 +3,6 @@ import 'package:weaco/domain/user/use_case/log_out_use_case.dart'; import '../../../mock/data/user/repository/mock_user_auth_repository_impl.dart'; - void main() { group('LogOutUseCase 클래스', () { final userAuthRepository = MockUserAuthRepositoryImpl(); @@ -13,25 +12,13 @@ void main() { setUp(() => userAuthRepository.initMockData()); group('logOut 메서드는', () { - test('로그아웃 실패를 반환한다.', () async { - // Given - userAuthRepository.isLogOut = false; - final expectedResult = await userAuthRepository.logOut(); - - // When - final actual = await useCase.execute(); - - // Then - expect(actual, expectedResult); - }); - - test('로그아웃 성공을 반환한다.', () async { + test('한 번 호출 된다.', () async { // Given - userAuthRepository.isLogOut = true; - final expectedResult = await userAuthRepository.logOut(); + int expectedResult = 1; // When - final actual = await useCase.execute(); + await useCase.execute(); + final actual = userAuthRepository.logOutCallCount; // Then expect(actual, expectedResult); diff --git a/test/domain/user/use_case/sign_in_use_case_test.dart b/test/domain/user/use_case/sign_in_use_case_test.dart index bc9de1b8..af3a56dc 100644 --- a/test/domain/user/use_case/sign_in_use_case_test.dart +++ b/test/domain/user/use_case/sign_in_use_case_test.dart @@ -38,42 +38,6 @@ void main() { expect(mockUserAuthRepositoryImpl.methodParameter, expectParameter); }); - test('일치하는 유저가 없을시 false를 반환한다.', () async { - final expectParameter = UserAuth( - email: 'qoophon@gmail.com', - password: 'password', - ); - - mockUserAuthRepositoryImpl.addUserAuth( - UserAuth( - email: 'qoophon@gmail.com', - password: 'password1', - ), - ); - - final actualReturnValue = - await signInUseCase.execute(userAuth: expectParameter); - - expect(actualReturnValue, false); - }); - test('일치하는 유저가 있을 시 true를 반환한다.', () async { - final expectParameter = UserAuth( - email: 'qoophon@gmail.com', - password: 'password', - ); - - mockUserAuthRepositoryImpl.addUserAuth( - UserAuth( - email: 'qoophon@gmail.com', - password: 'password', - ), - ); - - final actualReturnValue = - await signInUseCase.execute(userAuth: expectParameter); - - expect(actualReturnValue, true); - }); }); }); } diff --git a/test/domain/user/use_case/sign_out_use_case_test.dart b/test/domain/user/use_case/sign_out_use_case_test.dart index c1d684da..35fe8376 100644 --- a/test/domain/user/use_case/sign_out_use_case_test.dart +++ b/test/domain/user/use_case/sign_out_use_case_test.dart @@ -9,31 +9,19 @@ void main() { final SignOutUseCase useCase = SignOutUseCase(userAuthRepository: userAuthRepository); - group('signOut 메서드는', () { + group('execute() 메서드는', () { setUp(() => userAuthRepository.initMockData()); - test('회원 탈퇴에 실패한다.', () async { + test('userAuthRepository.signOut() 메서드를 1회 호출한다.', () async { // Given - const bool expectedResult = false; - userAuthRepository.isSignOut = expectedResult; + const int expectedResult = 1; // When - final result = await useCase.execute(); + await useCase.execute(); + final actual = userAuthRepository.signOutCallCount; // Then - expect(result, expectedResult); - }); - - test('회원 탈퇴에 성공한다.', () async { - // Given - const bool expectedResult = true; - userAuthRepository.isSignOut = expectedResult; - - // When - final result = await useCase.execute(); - - // Then - expect(result, expectedResult); + expect(actual, expectedResult); }); }); }); diff --git a/test/mock/core/firebase/mock_firestore_service_impl.dart b/test/mock/core/firebase/mock_firestore_service_impl.dart index 4c06ace9..a4df879c 100644 --- a/test/mock/core/firebase/mock_firestore_service_impl.dart +++ b/test/mock/core/firebase/mock_firestore_service_impl.dart @@ -5,14 +5,16 @@ class MockFirestoreServiceImpl implements TransactionService { final _fakeFirestore = FakeFirebaseFirestore(); @override - Future run(Function callBack) async { - return await _fakeFirestore.runTransaction((transaction) async { - return await callBack(transaction); + Future run(Function callBack) async { + await _fakeFirestore.runTransaction((transaction) async { + await callBack(transaction); }).then( - (value) => true, + (value) { + return; + }, onError: (e) { // throw Exception('피드 업로드에 실패 하였습니다.'); - throw Exception(e); + throw Exception('mockFireStore: $e'); }, ); } diff --git a/test/mock/data/feed/data_source/mock_remote_feed_data_source.dart b/test/mock/data/feed/data_source/mock_remote_feed_data_source.dart index 766dce0f..cd4402af 100644 --- a/test/mock/data/feed/data_source/mock_remote_feed_data_source.dart +++ b/test/mock/data/feed/data_source/mock_remote_feed_data_source.dart @@ -26,13 +26,12 @@ class MockRemoteFeedDataSource implements RemoteFeedDataSource { } @override - Future deleteFeed({ + Future deleteFeed({ required Transaction transaction, required String id, }) async { deleteFeedParamId = id; deleteFeedMethodCallCount++; - return deleteFeedReturnValue; } @override @@ -76,7 +75,7 @@ class MockRemoteFeedDataSource implements RemoteFeedDataSource { } @override - Future saveFeed({ + Future saveFeed({ required Transaction transaction, required Feed feed, }) async { @@ -87,6 +86,5 @@ class MockRemoteFeedDataSource implements RemoteFeedDataSource { if (saveFeedReturnValue) { feedList.add(feed); } - return saveFeedReturnValue; } } diff --git a/test/mock/data/feed/repository/mock_feed_repository_impl.dart b/test/mock/data/feed/repository/mock_feed_repository_impl.dart index ed39ae1c..2bd0ac84 100644 --- a/test/mock/data/feed/repository/mock_feed_repository_impl.dart +++ b/test/mock/data/feed/repository/mock_feed_repository_impl.dart @@ -57,10 +57,10 @@ class MockFeedRepositoryImpl implements FeedRepository { /// [getFeedParamId]에 [id] 저장 /// [getFeedResult] 반환 @override - Future getFeed({required String id}) async { + Future getFeed({required String id}) async { getFeedCallCount++; methodParameterMap['id'] = id; - return getFeedResult; + return getFeedResult!; } /// [_fakeFeedList]에서 조건에 맞는 피드 데이터를 찾아서 리스트로 반환 diff --git a/test/mock/data/file/data_source/local/mock_local_file_data_source_impl.dart b/test/mock/data/file/data_source/local/mock_local_file_data_source_impl.dart index f883b1c5..ea1e736b 100644 --- a/test/mock/data/file/data_source/local/mock_local_file_data_source_impl.dart +++ b/test/mock/data/file/data_source/local/mock_local_file_data_source_impl.dart @@ -11,10 +11,11 @@ class MockLocalFileDataSourceImpl implements LocalFileDataSource { methodResult.clear(); methodParameter.clear(); methodCallCount.clear(); + methodResult['getImage'] = File('test/mock/assets/origin.png'); } @override - Future getImage({required ImageType imageType}) async { + Future getImage({required ImageType imageType}) async { methodCallCount['getImage'] = (methodCallCount['getImage'] ?? 0) + 1; methodParameter['isOrigin'] = imageType; return methodResult['getImage']; @@ -29,7 +30,7 @@ class MockLocalFileDataSourceImpl implements LocalFileDataSource { } @override - Future getCompressedImage() { + Future getCompressedImage() { methodCallCount['getImage'] = (methodCallCount['getImage'] ?? 0) + 1; return methodResult['getImage']; } diff --git a/test/mock/data/file/repository/mock_file_repository_impl.dart b/test/mock/data/file/repository/mock_file_repository_impl.dart index bcfb508a..bd8e7fd5 100644 --- a/test/mock/data/file/repository/mock_file_repository_impl.dart +++ b/test/mock/data/file/repository/mock_file_repository_impl.dart @@ -7,7 +7,7 @@ class MockFileRepositoryImpl implements FileRepository { int saveImageCallCount = 0; int saveOotdImageCallCount = 0; final Map methodParameterMap = {}; - File? getImageResult; + File getImageResult = File('test/mock/assets/cropped.png'); List saveOotdImageResult = ['', '']; bool saveImageResult = false; @@ -20,16 +20,15 @@ class MockFileRepositoryImpl implements FileRepository { } @override - Future getImage({required ImageType imageType}) async { + Future getImage({required ImageType imageType}) async { getImageCallCount++; return getImageResult; } @override - Future saveImage({required bool isOrigin, required File file, List? compressedImage}) async { + Future saveImage({required bool isOrigin, required File file, List? compressedImage}) async { saveImageCallCount++; methodParameterMap['data'] = file; - return saveImageResult; } @override diff --git a/test/mock/data/user/data_source/mock_remote_user_profile_data_source.dart b/test/mock/data/user/data_source/mock_remote_user_profile_data_source.dart index 43c9b390..42b3b0cb 100644 --- a/test/mock/data/user/data_source/mock_remote_user_profile_data_source.dart +++ b/test/mock/data/user/data_source/mock_remote_user_profile_data_source.dart @@ -30,33 +30,30 @@ class MockRemoteUserProfileDataSourceImpl } @override - Future getUserProfile({String? email}) { + Future getUserProfile({String? email}) async { getUserProfileMethodCallCount++; methodEmailParameter = email; - return Future.value(getUserProfileResult); + return getUserProfileResult!; } @override - Future updateUserProfile({ + Future updateUserProfile({ required Transaction transaction, UserProfile? userProfile, }) async { updateUserProfileMethodCallCount++; methodUserProfileParameter = userProfile; - return isUpdated; } @override - Future saveUserProfile({required UserProfile userProfile}) async { + Future saveUserProfile({required UserProfile userProfile}) async { saveUserProfileMethodCallCount++; methodUserProfileParameter = userProfile; - return isSaved; } @override - Future removeUserProfile({String? email}) async { + Future removeUserProfile({String? email}) async { removeUserProfileMethodCallCount++; methodEmailParameter = email; - return isRemoved; } }