diff --git a/test/helpers/mock_factories.dart b/test/helpers/mock_factories.dart index 8b7edde..ea27b6e 100644 --- a/test/helpers/mock_factories.dart +++ b/test/helpers/mock_factories.dart @@ -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 load() async => _hallOfFame; + + @override + Future save(HallOfFame hallOfFame) async { + _hallOfFame = hallOfFame; + return true; + } + + @override + Future addEntry(HallOfFameEntry entry) async { + _hallOfFame = _hallOfFame.addEntry(entry); + return true; + } + + @override + Future deleteEntry(String id) async { + _hallOfFame = _hallOfFame.removeEntry(id); + return true; + } + + @override + Future clear() async { + _hallOfFame = HallOfFame.empty(); + return true; + } +} + +/// 테스트용 Fake StatisticsStorage +/// +/// 파일 시스템 접근 없이 메모리에서 동작 +class FakeStatisticsStorage extends StatisticsStorage { + CumulativeStatistics _stats = CumulativeStatistics.empty(); + + @override + Future loadCumulative() async => _stats; + + @override + Future saveCumulative(CumulativeStatistics stats) async { + _stats = stats; + return true; + } + + @override + Future mergeSession(SessionStatistics session) async { + _stats = _stats.mergeSession(session); + return true; + } + + @override + Future updateHighestLevel(int level) async { + if (level <= _stats.highestLevel) return true; + _stats = _stats.updateHighestLevel(level); + return true; + } + + @override + Future updateHighestGold(int gold) async { + if (gold <= _stats.highestGoldHeld) return true; + _stats = _stats.updateHighestGold(gold); + return true; + } + + @override + Future recordGameStart() async { + _stats = _stats.recordGameStart(); + return true; + } + + @override + Future recordGameComplete() async { + _stats = _stats.recordGameComplete(); + return true; + } + + @override + Future clear() async { + _stats = CumulativeStatistics.empty(); + return true; + } +} diff --git a/test/helpers/test_setup.dart b/test/helpers/test_setup.dart new file mode 100644 index 0000000..306675b --- /dev/null +++ b/test/helpers/test_setup.dart @@ -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 {}; + return null; + }, + ); + } + + /// 모든 싱글톤 서비스 정리 + /// + /// tearDown에서 호출하여 타이머 및 리소스 정리 + static void resetAllServices() { + AudioService.resetAll(); + } +}