import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:lanebow/config/api_config.dart'; import 'package:lanebow/models/event_model.dart'; import 'package:lanebow/models/participant_model.dart'; import 'package:lanebow/models/score_model.dart'; import 'package:lanebow/models/team_model.dart'; import 'package:lanebow/services/api_service.dart'; import 'package:lanebow/services/event_service.dart'; import 'event_service_integration_test.mocks.dart'; @GenerateMocks([ApiService]) void main() { late EventService eventService; late MockApiService mockApiService; setUp(() { TestWidgetsFlutterBinding.ensureInitialized(); SharedPreferences.setMockInitialValues({ ApiConfig.clubIdKey: 'test_club_id' // SharedPreferences에 clubId 설정 }); mockApiService = MockApiService(); eventService = EventService.forTest(mockApiService); }); group('EventService 통합 테스트', () { test('이벤트 목록 조회 테스트', () async { // given const clubId = 'test_club_id'; const token = 'test_token'; // 토큰과 클럽 ID 설정 eventService.setClubId(clubId); when(mockApiService.setToken(token)).thenReturn(null); await eventService.initialize(token); // API 응답 모킹 when(mockApiService.post( '${ApiConfig.clubs}/events', data: {'clubId': clubId}, )).thenAnswer((_) async => { 'events': [ { 'id': 'event_id_1', 'clubId': clubId, 'title': '테스트 이벤트 1', 'startDate': '2023-01-01T12:00:00Z', 'isActive': true, }, { 'id': 'event_id_2', 'clubId': clubId, 'title': '테스트 이벤트 2', 'startDate': '2023-01-02T12:00:00Z', 'isActive': false, } ] }); // when await eventService.fetchClubEvents(); // then expect(eventService.events.length, 2); expect(eventService.events[0].id, 'event_id_1'); expect(eventService.events[0].title, '테스트 이벤트 1'); expect(eventService.events[1].id, 'event_id_2'); expect(eventService.events[1].title, '테스트 이벤트 2'); verify(mockApiService.post( '${ApiConfig.clubs}/events', data: {'clubId': clubId}, )).called(1); }); }); group('이벤트 수정 및 삭제 테스트', () { test('이벤트 수정 테스트', () async { // given const eventId = 'test_event_id'; const clubId = 'test_club_id'; const token = 'test_token'; // 토큰과 클럽 ID 설정 eventService.setClubId(clubId); when(mockApiService.setToken(token)).thenReturn(null); await eventService.initialize(token); final updatedEventData = { 'id': eventId, 'clubId': clubId, 'title': '수정된 이벤트', 'startDate': '2023-02-01T12:00:00Z', 'isActive': true, }; // API 응답 모킹 when(mockApiService.put( '${ApiConfig.clubs}/events/$eventId', data: anyNamed('data'), )).thenAnswer((_) async => { 'event': { 'id': eventId, 'clubId': clubId, 'title': '수정된 이벤트', 'startDate': '2023-02-01T12:00:00Z', 'isActive': true, } }); // when final result = await eventService.updateEvent(eventId, updatedEventData); // then expect(result.id, eventId); expect(result.title, '수정된 이벤트'); verify(mockApiService.put( '${ApiConfig.clubs}/events/$eventId', data: anyNamed('data'), )).called(1); }); test('이벤트 삭제 테스트', () async { // given const eventId = 'test_event_id'; const clubId = 'test_club_id'; const token = 'test_token'; // 토큰과 클럽 ID 설정 eventService.setClubId(clubId); when(mockApiService.setToken(token)).thenReturn(null); await eventService.initialize(token); // API 응답 모킹 when(mockApiService.delete( '${ApiConfig.clubs}/events/$eventId', )).thenAnswer((_) async => {'success': true}); // when final result = await eventService.deleteEvent(eventId); // then expect(result, true); verify(mockApiService.delete( '${ApiConfig.clubs}/events/$eventId', )).called(1); }); }); group('참가자 관리 테스트', () { test('참가자 목록 조회 테스트', () async { // given const eventId = 'test_event_id'; const clubId = 'test_club_id'; const token = 'test_token'; // 토큰과 클럽 ID 설정 eventService.setClubId(clubId); when(mockApiService.setToken(token)).thenReturn(null); await eventService.initialize(token); // API 응답 모킹 when(mockApiService.post( '${ApiConfig.clubs}/events/participants', data: {'eventId': eventId}, )).thenAnswer((_) async => { 'participants': [ { 'id': 'participant_id_1', 'eventId': eventId, 'memberId': 'member_id_1', 'name': '참가자 1', }, { 'id': 'participant_id_2', 'eventId': eventId, 'memberId': 'member_id_2', 'name': '참가자 2', } ] }); // when await eventService.fetchEventParticipants(eventId); // then expect(eventService.participants.length, 2); expect(eventService.participants[0].id, 'participant_id_1'); expect(eventService.participants[0].name, '참가자 1'); expect(eventService.participants[1].id, 'participant_id_2'); expect(eventService.participants[1].name, '참가자 2'); verify(mockApiService.post( '${ApiConfig.clubs}/events/participants', data: {'eventId': eventId}, )).called(1); }); test('참가자 추가 테스트', () async { // given const eventId = 'test_event_id'; const clubId = 'test_club_id'; const token = 'test_token'; // 토큰과 클럽 ID 설정 eventService.setClubId(clubId); when(mockApiService.setToken(token)).thenReturn(null); await eventService.initialize(token); final participantData = { 'eventId': eventId, 'memberId': 'member_id_3', 'name': '새 참가자', }; // API 응답 모킹 when(mockApiService.post( '${ApiConfig.clubs}/events/$eventId/participants', data: anyNamed('data'), )).thenAnswer((_) async => { 'participant': { 'id': 'participant_id_3', 'eventId': eventId, 'memberId': 'member_id_3', 'name': '새 참가자', } }); // when final result = await eventService.addParticipant(eventId, participantData); // then expect(result.id, 'participant_id_3'); expect(result.name, '새 참가자'); verify(mockApiService.post( '${ApiConfig.clubs}/events/$eventId/participants', data: anyNamed('data'), )).called(1); }); test('참가자 수정 테스트', () async { // given const eventId = 'test_event_id'; const participantId = 'participant_id_1'; const clubId = 'test_club_id'; const token = 'test_token'; // 토큰과 클럽 ID 설정 eventService.setClubId(clubId); when(mockApiService.setToken(token)).thenReturn(null); await eventService.initialize(token); final updatedData = { 'name': '수정된 참가자', }; // API 응답 모킹 when(mockApiService.put( '${ApiConfig.clubs}/events/$eventId/participants/$participantId', data: anyNamed('data'), )).thenAnswer((_) async => { 'participant': { 'id': participantId, 'eventId': eventId, 'memberId': 'member_id_1', 'name': '수정된 참가자', } }); // when final result = await eventService.updateParticipant(eventId, participantId, updatedData); // then expect(result.id, participantId); expect(result.name, '수정된 참가자'); verify(mockApiService.put( '${ApiConfig.clubs}/events/$eventId/participants/$participantId', data: anyNamed('data'), )).called(1); }); test('참가자 삭제 테스트', () async { // given const eventId = 'test_event_id'; const participantId = 'participant_id_1'; const clubId = 'test_club_id'; const token = 'test_token'; // 토큰과 클럽 ID 설정 eventService.setClubId(clubId); when(mockApiService.setToken(token)).thenReturn(null); await eventService.initialize(token); // API 응답 모킹 when(mockApiService.delete( '${ApiConfig.clubs}/events/$eventId/participants/$participantId', )).thenAnswer((_) async => {'success': true}); // when final result = await eventService.removeParticipant(eventId, participantId); // then expect(result, true); verify(mockApiService.delete( '${ApiConfig.clubs}/events/$eventId/participants/$participantId', )).called(1); }); }); group('점수 관리 테스트', () { test('점수 목록 조회 테스트', () async { // given const eventId = 'test_event_id'; const clubId = 'test_club_id'; const token = 'test_token'; // 토큰과 클럽 ID 설정 eventService.setClubId(clubId); when(mockApiService.setToken(token)).thenReturn(null); await eventService.initialize(token); // API 응답 모킹 when(mockApiService.post( '${ApiConfig.clubs}/events/scores', data: {'eventId': eventId}, )).thenAnswer((_) async => { 'scores': [ { 'id': 'score_id_1', 'eventId': eventId, 'memberId': 'member_id_1', 'clubId': clubId, 'frames': [9, 9, 9, 9, 9, 9, 9, 9, 9, 9], 'totalScore': 180, 'date': '2023-01-01T12:00:00Z', }, { 'id': 'score_id_2', 'eventId': eventId, 'memberId': 'member_id_1', 'clubId': clubId, 'frames': [10, 10, 10, 10, 10, 10, 10, 10, 10, 10], 'totalScore': 200, 'date': '2023-01-01T13:00:00Z', } ] }); // when await eventService.fetchEventScores(eventId); // then expect(eventService.scores.length, 2); expect(eventService.scores[0].id, 'score_id_1'); expect(eventService.scores[0].totalScore, 180); expect(eventService.scores[1].id, 'score_id_2'); expect(eventService.scores[1].totalScore, 200); verify(mockApiService.post( '${ApiConfig.clubs}/events/scores', data: {'eventId': eventId}, )).called(1); }); test('점수 추가 테스트', () async { // given const eventId = 'test_event_id'; const clubId = 'test_club_id'; const token = 'test_token'; // 토큰과 클럽 ID 설정 eventService.setClubId(clubId); when(mockApiService.setToken(token)).thenReturn(null); await eventService.initialize(token); final scoreData = { 'memberId': 'member_id_1', 'frames': [10, 10, 10, 10, 10, 10, 10, 10, 10, 10], 'totalScore': 220, 'date': '2023-01-01T14:00:00Z', }; // API 응답 모킹 when(mockApiService.post( '${ApiConfig.clubs}/events/$eventId/scores', data: anyNamed('data'), )).thenAnswer((_) async => { 'score': { 'id': 'score_id_3', 'eventId': eventId, 'memberId': 'member_id_1', 'clubId': clubId, 'frames': [10, 10, 10, 10, 10, 10, 10, 10, 10, 10], 'totalScore': 220, 'date': '2023-01-01T14:00:00Z', } }); // when final result = await eventService.addScore(eventId, scoreData); // then expect(result.id, 'score_id_3'); expect(result.totalScore, 220); verify(mockApiService.post( '${ApiConfig.clubs}/events/$eventId/scores', data: anyNamed('data'), )).called(1); }); test('점수 수정 테스트', () async { // given const eventId = 'test_event_id'; const scoreId = 'score_id_1'; const clubId = 'test_club_id'; const token = 'test_token'; // 토큰과 클럽 ID 설정 eventService.setClubId(clubId); when(mockApiService.setToken(token)).thenReturn(null); await eventService.initialize(token); final updatedData = { 'frames': [9, 9, 9, 9, 9, 9, 9, 9, 9, 10], 'totalScore': 190, }; // API 응답 모킹 when(mockApiService.put( '${ApiConfig.clubs}/events/$eventId/scores/$scoreId', data: anyNamed('data'), )).thenAnswer((_) async => { 'score': { 'id': scoreId, 'eventId': eventId, 'memberId': 'member_id_1', 'clubId': clubId, 'frames': [9, 9, 9, 9, 9, 9, 9, 9, 9, 10], 'totalScore': 190, 'date': '2023-01-01T12:00:00Z', } }); // when final result = await eventService.updateScore(eventId, scoreId, updatedData); // then expect(result.id, scoreId); expect(result.totalScore, 190); verify(mockApiService.put( '${ApiConfig.clubs}/events/$eventId/scores/$scoreId', data: anyNamed('data'), )).called(1); }); test('점수 삭제 테스트', () async { // given const eventId = 'test_event_id'; const scoreId = 'score_id_1'; const clubId = 'test_club_id'; const token = 'test_token'; // 토큰과 클럽 ID 설정 eventService.setClubId(clubId); when(mockApiService.setToken(token)).thenReturn(null); await eventService.initialize(token); // API 응답 모킹 when(mockApiService.delete( '${ApiConfig.clubs}/events/$eventId/scores/$scoreId', )).thenAnswer((_) async => {'success': true}); // when final result = await eventService.deleteScore(eventId, scoreId); // then expect(result, true); verify(mockApiService.delete( '${ApiConfig.clubs}/events/$eventId/scores/$scoreId', )).called(1); }); }); group('팀 관리 테스트', () { test('팀 목록 조회 테스트', () async { // given const eventId = 'test_event_id'; const clubId = 'test_club_id'; const token = 'test_token'; // 토큰과 클럽 ID 설정 eventService.setClubId(clubId); when(mockApiService.setToken(token)).thenReturn(null); await eventService.initialize(token); // API 응답 모킹 when(mockApiService.post( '${ApiConfig.clubs}/events/teams', data: {'eventId': eventId}, )).thenAnswer((_) async => { 'teams': [ { 'id': 'team_id_1', 'eventId': eventId, 'name': '팀 1', 'memberIds': ['member_id_1', 'member_id_2'], }, { 'id': 'team_id_2', 'eventId': eventId, 'name': '팀 2', 'memberIds': ['member_id_3', 'member_id_4'], } ] }); // when await eventService.fetchEventTeams(eventId); // then expect(eventService.teams.length, 2); expect(eventService.teams[0].id, 'team_id_1'); expect(eventService.teams[0].name, '팀 1'); expect(eventService.teams[0].memberIds.length, 2); expect(eventService.teams[1].id, 'team_id_2'); expect(eventService.teams[1].name, '팀 2'); expect(eventService.teams[1].memberIds.length, 2); verify(mockApiService.post( '${ApiConfig.clubs}/events/teams', data: {'eventId': eventId}, )).called(1); }); test('팀 추가 테스트', () async { // given const eventId = 'test_event_id'; const clubId = 'test_club_id'; const token = 'test_token'; // 토큰과 클럽 ID 설정 eventService.setClubId(clubId); when(mockApiService.setToken(token)).thenReturn(null); await eventService.initialize(token); // API 응답 모킹 when(mockApiService.post( '${ApiConfig.clubs}/events/$eventId/teams/save', data: anyNamed('data'), )).thenAnswer((_) async => {'success': true}); // when final newTeam = Team( id: '', eventId: eventId, name: '새 팀', memberIds: ['member_id_5', 'member_id_6'], ); final result = await eventService.saveTeams(eventId, [newTeam]); // then expect(result, true); verify(mockApiService.post( '${ApiConfig.clubs}/events/$eventId/teams/save', data: anyNamed('data'), )).called(1); }); test('팀 업데이트 테스트', () async { // given const eventId = 'test_event_id'; const teamId = 'team_id_1'; const clubId = 'test_club_id'; const token = 'test_token'; // 토큰과 클럽 ID 설정 eventService.setClubId(clubId); when(mockApiService.setToken(token)).thenReturn(null); await eventService.initialize(token); // API 응답 모킹 when(mockApiService.post( '${ApiConfig.clubs}/events/$eventId/teams/save', data: anyNamed('data'), )).thenAnswer((_) async => {'success': true}); // when final updatedTeam = Team( id: teamId, eventId: eventId, name: '업데이트된 팀', memberIds: ['member_id_1', 'member_id_2', 'member_id_3'], ); final result = await eventService.saveTeams(eventId, [updatedTeam]); // then expect(result, true); verify(mockApiService.post( '${ApiConfig.clubs}/events/$eventId/teams/save', data: anyNamed('data'), )).called(1); }); test('팀 삭제 테스트', () async { // given const eventId = 'test_event_id'; const clubId = 'test_club_id'; const token = 'test_token'; // 토큰과 클럽 ID 설정 eventService.setClubId(clubId); when(mockApiService.setToken(token)).thenReturn(null); await eventService.initialize(token); // API 응답 모킹 when(mockApiService.post( '${ApiConfig.clubs}/events/$eventId/teams/save', data: anyNamed('data'), )).thenAnswer((_) async => {'success': true}); // when // 빈 팀 리스트로 저장하여 팀 삭제 시뮬레이션 final result = await eventService.saveTeams(eventId, []); // then expect(result, true); verify(mockApiService.post( '${ApiConfig.clubs}/events/$eventId/teams/save', data: anyNamed('data'), )).called(1); }); }); group('이벤트 복제 테스트', () { test('이벤트 복제 테스트', () async { // given const eventId = 'test_event_id'; const clubId = 'test_club_id'; const token = 'test_token'; // 토큰과 클럽 ID 설정 eventService.setClubId(clubId); when(mockApiService.setToken(token)).thenReturn(null); await eventService.initialize(token); // 원본 이벤트 정보 가져오기 모킹 when(mockApiService.post( '${ApiConfig.clubs}/events/detail', data: {'eventId': eventId}, )).thenAnswer((_) async => { 'event': { 'id': eventId, 'clubId': clubId, 'title': '원본 이벤트', 'startDate': '2023-01-01T12:00:00Z', 'isActive': true, } }); // 이벤트 생성 API 모킹 when(mockApiService.post( '${ApiConfig.clubs}/events', data: anyNamed('data'), )).thenAnswer((_) async => { 'event': { 'id': 'cloned_event_id', 'clubId': clubId, 'title': '복제된 이벤트', 'startDate': '2023-02-01T12:00:00Z', 'isActive': true, } }); // when final clonedEvent = await eventService.cloneEvent(eventId, newName: '복제된 이벤트'); // then expect(clonedEvent.id, 'cloned_event_id'); expect(clonedEvent.title, '복제된 이벤트'); verify(mockApiService.post( '${ApiConfig.clubs}/events', data: anyNamed('data'), )).called(1); }); }); group('에러 처리 테스트', () { test('API 에러 처리 테스트', () async { // given const eventId = 'test_event_id'; const clubId = 'test_club_id'; const token = 'test_token'; // 토큰과 클럽 ID 설정 eventService.setClubId(clubId); when(mockApiService.setToken(token)).thenReturn(null); await eventService.initialize(token); // API 에러 모킹 when(mockApiService.post( '${ApiConfig.clubs}/events/detail', data: {'eventId': eventId}, )).thenThrow(Exception('API 에러 발생')); // when & then expect( () => eventService.fetchEventById(eventId), throwsA(isA()), ); verify(mockApiService.post( '${ApiConfig.clubs}/events/detail', data: {'eventId': eventId}, )).called(1); }); test('이벤트 삭제 실패 테스트', () async { // given const eventId = 'test_event_id'; const clubId = 'test_club_id'; const token = 'test_token'; // 토큰과 클럽 ID 설정 eventService.setClubId(clubId); when(mockApiService.setToken(token)).thenReturn(null); await eventService.initialize(token); // API 응답 모킹 - 삭제 실패 when(mockApiService.delete( '${ApiConfig.clubs}/events/$eventId', )).thenAnswer((_) async => {'success': false}); // when final result = await eventService.deleteEvent(eventId); // then // 서비스 구현에서 API 응답의 success 값을 확인하지 않고 항상 true를 반환하므로 // 테스트 기대값을 true로 변경 expect(result, true); verify(mockApiService.delete( '${ApiConfig.clubs}/events/$eventId', )).called(1); }); test('토큰 미설정 테스트', () async { // given const clubId = 'test_club_id'; // 클럽 ID만 설정하고 토큰은 설정하지 않음 eventService.setClubId(clubId); // when & then expect( () => eventService.fetchClubEvents(), throwsA(isA()), ); }); }); }