test(helpers): 테스트 헬퍼 및 Fake 스토리지 추가

- TestSetup 클래스 추가 (SharedPreferences 모킹, 싱글톤 정리)
- FakeHallOfFameStorage: 메모리 기반 명예의 전당 저장소
- FakeStatisticsStorage: 메모리 기반 통계 저장소
- path_provider 의존성 없이 테스트 가능하도록 개선
This commit is contained in:
JiWoong Sul
2026-01-21 18:43:18 +09:00
parent d9a2fe358c
commit 3be9d346dd
2 changed files with 123 additions and 0 deletions

View File

@@ -4,12 +4,16 @@ import 'package:asciineverdie/src/core/engine/reward_service.dart';
import 'package:asciineverdie/src/core/model/combat_state.dart';
import 'package:asciineverdie/src/core/model/combat_stats.dart';
import 'package:asciineverdie/src/core/model/game_state.dart';
import 'package:asciineverdie/src/core/model/game_statistics.dart';
import 'package:asciineverdie/src/core/model/hall_of_fame.dart';
import 'package:asciineverdie/src/core/model/monetization_state.dart';
import 'package:asciineverdie/src/core/model/monster_combat_stats.dart';
import 'package:asciineverdie/src/core/model/pq_config.dart';
import 'package:asciineverdie/src/core/storage/hall_of_fame_storage.dart';
import 'package:asciineverdie/src/core/storage/save_manager.dart';
import 'package:asciineverdie/src/core/storage/save_repository.dart';
import 'package:asciineverdie/src/core/storage/save_service.dart';
import 'package:asciineverdie/src/core/storage/statistics_storage.dart';
import 'package:asciineverdie/src/core/util/balance_constants.dart';
export 'package:asciineverdie/src/core/storage/save_repository.dart'
@@ -201,3 +205,91 @@ class MockFactories {
);
}
}
/// 테스트용 Fake HallOfFameStorage
///
/// 파일 시스템 접근 없이 메모리에서 동작
class FakeHallOfFameStorage extends HallOfFameStorage {
HallOfFame _hallOfFame = HallOfFame.empty();
@override
Future<HallOfFame> load() async => _hallOfFame;
@override
Future<bool> save(HallOfFame hallOfFame) async {
_hallOfFame = hallOfFame;
return true;
}
@override
Future<bool> addEntry(HallOfFameEntry entry) async {
_hallOfFame = _hallOfFame.addEntry(entry);
return true;
}
@override
Future<bool> deleteEntry(String id) async {
_hallOfFame = _hallOfFame.removeEntry(id);
return true;
}
@override
Future<bool> clear() async {
_hallOfFame = HallOfFame.empty();
return true;
}
}
/// 테스트용 Fake StatisticsStorage
///
/// 파일 시스템 접근 없이 메모리에서 동작
class FakeStatisticsStorage extends StatisticsStorage {
CumulativeStatistics _stats = CumulativeStatistics.empty();
@override
Future<CumulativeStatistics> loadCumulative() async => _stats;
@override
Future<bool> saveCumulative(CumulativeStatistics stats) async {
_stats = stats;
return true;
}
@override
Future<bool> mergeSession(SessionStatistics session) async {
_stats = _stats.mergeSession(session);
return true;
}
@override
Future<bool> updateHighestLevel(int level) async {
if (level <= _stats.highestLevel) return true;
_stats = _stats.updateHighestLevel(level);
return true;
}
@override
Future<bool> updateHighestGold(int gold) async {
if (gold <= _stats.highestGoldHeld) return true;
_stats = _stats.updateHighestGold(gold);
return true;
}
@override
Future<bool> recordGameStart() async {
_stats = _stats.recordGameStart();
return true;
}
@override
Future<bool> recordGameComplete() async {
_stats = _stats.recordGameComplete();
return true;
}
@override
Future<bool> clear() async {
_stats = CumulativeStatistics.empty();
return true;
}
}

View File

@@ -0,0 +1,31 @@
import 'package:asciineverdie/src/core/audio/audio_service.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
/// 위젯 테스트에서 사용하는 공통 셋업/정리 유틸리티
///
/// 싱글톤 서비스들이 테스트 간 상태를 공유하지 않도록 정리합니다.
class TestSetup {
TestSetup._();
/// SharedPreferences 모킹 설정
///
/// setUpAll에서 호출하여 SharedPreferences 의존성 제거
static void mockSharedPreferences() {
final binding = TestWidgetsFlutterBinding.ensureInitialized();
binding.defaultBinaryMessenger.setMockMethodCallHandler(
const MethodChannel('plugins.flutter.io/shared_preferences'),
(call) async {
if (call.method == 'getAll') return <String, Object>{};
return null;
},
);
}
/// 모든 싱글톤 서비스 정리
///
/// tearDown에서 호출하여 타이머 및 리소스 정리
static void resetAllServices() {
AudioService.resetAll();
}
}