tdd 진행

This commit is contained in:
2025-08-09 03:09:17 +09:00
parent ed8c7eacba
commit 6033d59590
74 changed files with 17804 additions and 395 deletions
@@ -0,0 +1,386 @@
import 'dart:async';
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/club_model.dart';
import 'package:lanebow/services/api_service.dart';
import 'package:lanebow/services/club_service.dart';
import 'package:lanebow/services/event_bus.dart';
import 'club_service_integration_test.mocks.dart';
@GenerateMocks([ApiService])
void main() {
late ClubService clubService;
late MockApiService mockApiService;
setUp(() {
TestWidgetsFlutterBinding.ensureInitialized();
SharedPreferences.setMockInitialValues({
ApiConfig.clubIdKey: 'test_club_id' // SharedPreferences에 clubId 설정
});
mockApiService = MockApiService();
// 모든 테스트에서 공통으로 사용되는 모킹 설정
when(mockApiService.post(
'/club',
data: {'clubId': 'test_club_id'},
)).thenAnswer((_) async => {
'id': 'test_club_id',
'name': '테스트 클럽',
'description': '테스트 클럽 설명',
'ownerId': 'owner_id',
});
clubService = ClubService.forTest(mockApiService);
});
group('ClubService 통합 테스트', () {
test('초기화 테스트', () async {
// given
const token = 'test_token';
const clubId = 'test_club_id';
// API 응답 모킹
when(mockApiService.setToken(token)).thenReturn(null);
when(mockApiService.post(
'${ApiConfig.clubs}',
data: {'clubId': clubId},
)).thenAnswer((_) async => {
'id': clubId,
'name': '테스트 클럽',
'description': '테스트 클럽 설명',
'ownerId': 'owner_id',
'isActive': true,
});
// when
await clubService.initialize(token);
// then
expect(clubService.currentClub, isNotNull);
expect(clubService.currentClub?.id, clubId);
expect(clubService.currentClub?.name, '테스트 클럽');
verify(mockApiService.setToken(token)).called(1);
// initialize에서 이미 fetchClubById를 호출하기 때문에 호출 횟수 검증을 제거합니다.
});
test('사용자 클럽 목록 조회 테스트', () async {
// given
const token = 'test_token';
// 토큰 설정
when(mockApiService.setToken(token)).thenReturn(null);
await clubService.initialize(token);
// API 응답 모킹
when(mockApiService.post('${ApiConfig.clubs}/user')).thenAnswer((_) async => [
{
'id': 'club_id_1',
'name': '테스트 클럽 1',
'description': '테스트 클럽 1 설명',
'ownerId': 'owner_id',
},
{
'id': 'club_id_2',
'name': '테스트 클럽 2',
'description': '테스트 클럽 2 설명',
'ownerId': 'owner_id',
}
]);
// when
await clubService.fetchUserClubs();
// then
expect(clubService.clubs.length, 2);
expect(clubService.clubs[0].id, 'club_id_1');
expect(clubService.clubs[0].name, '테스트 클럽 1');
expect(clubService.clubs[1].id, 'club_id_2');
expect(clubService.clubs[1].name, '테스트 클럽 2');
});
test('ID로 클럽 정보 조회 테스트', () async {
// given
const token = 'test_token';
const clubId = 'test_club_id';
// 토큰 설정
when(mockApiService.setToken(token)).thenReturn(null);
await clubService.initialize(token);
// API 응답 모킹
when(mockApiService.post(
'${ApiConfig.clubs}',
data: {'clubId': clubId},
)).thenAnswer((_) async => {
'id': clubId,
'name': '테스트 클럽',
'description': '테스트 클럽 설명',
'ownerId': 'owner_id',
'isActive': true,
});
// when
await clubService.fetchClubById(clubId);
// then
expect(clubService.currentClub, isNotNull);
expect(clubService.currentClub?.id, clubId);
expect(clubService.currentClub?.name, '테스트 클럽');
});
test('현재 클럽 설정 테스트', () async {
// given
const token = 'test_token';
const clubId = 'test_club_id';
// 토큰 설정
when(mockApiService.setToken(token)).thenReturn(null);
await clubService.initialize(token);
// API 응답 모킹
when(mockApiService.post(
'${ApiConfig.clubs}',
data: {'clubId': clubId},
)).thenAnswer((_) async => {
'id': clubId,
'name': '테스트 클럽',
'description': '테스트 클럽 설명',
'ownerId': 'owner_id',
'isActive': true,
});
// when
await clubService.setCurrentClub(clubId);
// then
expect(clubService.currentClub, isNotNull);
expect(clubService.currentClub?.id, clubId);
expect(clubService.currentClub?.name, '테스트 클럽');
});
test('클럽 선택 테스트', () async {
// given
const token = 'test_token';
const clubId = 'test_club_id';
// 토큰 설정
when(mockApiService.setToken(token)).thenReturn(null);
await clubService.initialize(token);
// API 응답 모킹
when(mockApiService.post(
'${ApiConfig.clubs}/select-club',
data: {'clubId': clubId},
)).thenAnswer((_) async => {'success': true});
when(mockApiService.post(
'${ApiConfig.clubs}',
data: {'clubId': clubId},
)).thenAnswer((_) async => {
'id': clubId,
'name': '테스트 클럽',
'description': '테스트 클럽 설명',
'ownerId': 'owner_id',
'isActive': true,
});
// EventBus 이벤트 리스너 설정
bool eventFired = false;
final completer = Completer<void>();
EventBus().on<ClubChangedEvent>().listen((event) {
eventFired = true;
expect(event.clubId, clubId);
completer.complete();
});
// when
await clubService.selectClub(clubId);
// 이벤트가 발생할 때까지 짧게 대기
await Future.any([completer.future, Future.delayed(const Duration(seconds: 1))]);
// then
expect(clubService.currentClub, isNotNull);
expect(clubService.currentClub?.id, clubId);
expect(clubService.currentClub?.name, '테스트 클럽');
expect(eventFired, true);
});
test('클럽 생성 테스트', () async {
// given
const token = 'test_token';
// 토큰 설정
when(mockApiService.setToken(token)).thenReturn(null);
await clubService.initialize(token);
final newClub = Club(
id: '',
name: '새 클럽',
description: '새 클럽 설명',
ownerId: 'owner_id',
);
// API 응답 모킹
when(mockApiService.post(
'${ApiConfig.clubs}',
data: anyNamed('data'),
)).thenAnswer((_) async => {
'club': {
'id': 'new_club_id',
'name': '새 클럽',
'description': '새 클럽 설명',
'ownerId': 'owner_id',
}
});
// when
final result = await clubService.createClub(newClub);
// then
expect(result.id, 'new_club_id');
expect(result.name, '새 클럽');
expect(clubService.currentClub?.id, 'new_club_id');
expect(clubService.clubs.length, 1);
expect(clubService.clubs[0].id, 'new_club_id');
});
test('클럽 정보 업데이트 테스트', () async {
// given
const token = 'test_token';
const clubId = 'test_club_id';
// 토큰 설정
when(mockApiService.setToken(token)).thenReturn(null);
await clubService.initialize(token);
// 클럽 목록 설정
when(mockApiService.post('${ApiConfig.clubs}/user')).thenAnswer((_) async => [
{
'id': clubId,
'name': '테스트 클럽',
'description': '테스트 클럽 설명',
'ownerId': 'owner_id',
}
]);
await clubService.fetchUserClubs();
final updates = {
'name': '수정된 클럽',
'description': '수정된 클럽 설명',
};
// API 응답 모킹
when(mockApiService.put(
ApiConfig.clubs,
data: {
'clubId': clubId,
...updates,
},
)).thenAnswer((_) async => {
'club': {
'id': clubId,
'name': '수정된 클럽',
'description': '수정된 클럽 설명',
'ownerId': 'owner_id',
}
});
// when
final result = await clubService.updateClub(clubId, updates);
// then
expect(result.id, clubId);
expect(result.name, '수정된 클럽');
expect(result.description, '수정된 클럽 설명');
expect(clubService.clubs[0].name, '수정된 클럽');
verify(mockApiService.put(
ApiConfig.clubs,
data: {
'clubId': clubId,
...updates,
},
)).called(1);
});
});
group('에러 처리 테스트', () {
test('토큰 미설정 테스트', () async {
// given
// 토큰을 설정하지 않음
// when & then
expect(
() => clubService.fetchUserClubs(),
returnsNormally, // 토큰이 없으면 조용히 반환됨
);
});
test('API 에러 처리 테스트', () async {
// given
const token = 'test_token';
const clubId = 'test_club_id';
// 토큰 설정
when(mockApiService.setToken(token)).thenReturn(null);
await clubService.initialize(token);
// API 에러 모킹
when(mockApiService.post(
'${ApiConfig.clubs}',
data: {'clubId': clubId},
)).thenThrow(Exception('API 에러 발생'));
// when & then
expect(
() => clubService.fetchClubById(clubId),
throwsA(isA<Exception>()),
);
});
test('클럽 생성 실패 테스트', () async {
// given
const token = 'test_token';
// 토큰 설정
when(mockApiService.setToken(token)).thenReturn(null);
await clubService.initialize(token);
final newClub = Club(
id: '',
name: '새 클럽',
description: '새 클럽 설명',
ownerId: 'owner_id',
);
// API 에러 모킹
when(mockApiService.post(
'${ApiConfig.clubs}',
data: anyNamed('data'),
)).thenThrow(Exception('클럽 생성 실패'));
// when & then
expect(
() => clubService.createClub(newClub),
throwsA(isA<Exception>()),
);
});
});
}