LCOV - code coverage report

Current view: | top level - lib/services - event_bus.dart |  |  | Coverage | Total | Hit
Test: | lcov.info |  | Lines: | 77.8 % | 194 | 151
Test Date: | 2025-08-12 03:21:51 |  | Functions: | - | 0 | 0

                Line data    Source code

           1              : import 'dart:async';
           2              : import 'dart:developer' as developer;
           3              : import 'package:flutter/foundation.dart';
           4              : import 'package:lanebow/utils/test_utils.dart';
           5              : import 'package:lanebow/utils/test_config.dart';
           6              :
           7              : // 이벤트 클래스들 - 클래스 외부로 이동
           8              : class ClubChangedEvent {
           9              :   final String clubId;
          10              :
          11            4 :   ClubChangedEvent(this.clubId);
          12              :
          13            4 :   @override
          14            8 :   String toString() => 'ClubChangedEvent(clubId: $clubId)';
          15              :
          16            0 :   @override
          17              :   bool operator ==(Object other) {
          18              :     if (identical(this, other)) return true;
          19            0 :     return other is ClubChangedEvent && other.clubId == clubId;
          20              :   }
          21              :
          22            0 :   @override
          23            0 :   int get hashCode => clubId.hashCode;
          24              : }
          25              :
          26              : class EventBus {
          27              :   // 테스트 환경에서 사용할 별도의 인스턴스 맵
          28           36 :   static final Map<String, EventBus> _testInstances = {};
          29              :
          30              :   // 기본 싱글톤 인스턴스
          31           42 :   static final EventBus _instance = EventBus._internal();
          32              :
          33              :   // 테스트 ID를 저장하는 변수 (테스트 격리용)
          34              :   static String? _currentTestId;
          35              :
          36              :   // 테스트 환경 초기화 상태 추적
          37              :   static bool _isTestEnvironmentReady = false;
          38              :
          39              :   // 테스트 환경 초기화 관련 로깅
          40           12 :   static void _logTestEnvironmentInit() {
          41              :     _isTestEnvironmentReady = true;
          42              :     if (kDebugMode) {
          43           24 :       debugPrint('EventBus: 테스트 환경 초기화 완료');
          44              :     }
          45              :   }
          46              :
          47              :   // 활성 구독 수 추적 (디버깅 및 메모리 누수 감지용)
          48              :   static int _activeSubscriptionCount = 0;
          49              :
          50              :   /// 현재 활성화된 테스트 인스턴스 수 반환
          51            3 :   static int get testInstanceCount => _testInstances.length;
          52              :
          53              :   // 테스트 재시도 횟수 추적 및 관리
          54              :   static int _testRetryCount = 0;
          55              :
          56              :   // 테스트 재시도 횟수 가져오기
          57            0 :   static int get testRetryCount => _testRetryCount;
          58              :
          59              :   // 테스트 재시도 횟수 증가
          60            0 :   static void incrementRetryCount() {
          61            0 :     _testRetryCount++;
          62            0 :     if (kDebugMode || TestConfig.instance.isVerboseLogging) {
          63            0 :       debugPrint('EventBus: 테스트 재시도 횟수 증가 - $_testRetryCount');
          64              :     }
          65              :   }
          66              :
          67              :   // 활성 구독 수 접근 게터
          68            2 :   static int get activeSubscriptionCount => _activeSubscriptionCount;
          69              :
          70              :   // 현재 테스트 ID 설정 메서드
          71           12 :   static void setCurrentTestId(String testId) {
          72              :     // 테스트 설정 로드 확인 및 로깅
          73           12 :     final config = TestConfig.instance;
          74           12 :     if (config.isVerboseLogging) {
          75            0 :       debugPrint('EventBus: 테스트 설정 로드 - asyncTimeout=${config.asyncTimeout}ms, testDelay=${config.testDelay}ms');
          76              :     }
          77              :     // 이전 테스트 ID가 있으면 해당 인스턴스 정리
          78            1 :     if (_currentTestId != null && _currentTestId != testId) {
          79            2 :       if (_testInstances.containsKey(_currentTestId!)) {
          80              :         try {
          81            3 :           _testInstances[_currentTestId!]!.dispose();
          82              :         } catch (e) {
          83              :           if (kDebugMode) {
          84            0 :             debugPrint('EventBus: 이전 인스턴스 dispose 중 오류 - $e');
          85              :           }
          86              :         } finally {
          87            2 :           _testInstances.remove(_currentTestId!);
          88              :         }
          89              :       }
          90              :     }
          91              :
          92              :     // 새 테스트 ID 설정
          93              :     _currentTestId = testId;
          94              :
          95              :     // 새 테스트 ID에 대한 인스턴스가 없으면 생성
          96           24 :     if (!_testInstances.containsKey(testId)) {
          97           36 :       _testInstances[testId] = EventBus._internal();
          98              :     } else {
          99              :       // 이미 존재하는 인스턴스라도 초기화 수행
         100            3 :       _testInstances[testId]!.reset();
         101              :     }
         102              :
         103              :     // 테스트 환경 초기화 로깅
         104           12 :     _logTestEnvironmentInit();
         105              :
         106              :     // 활성 구독 수 초기화
         107              :     _activeSubscriptionCount = 0;
         108              :
         109              :     // 테스트 재시도 횟수 초기화
         110              :     _testRetryCount = 0;
         111              :
         112              :     if (kDebugMode) {
         113           36 :       debugPrint('EventBus: 테스트 ID 설정됨 - $testId');
         114           36 :       developer.log('EventBus 메모리 상태: $_testInstances', name: 'EventBus');
         115              :     }
         116              :   }
         117              :
         118              :   // 현재 테스트 ID 초기화 메서드
         119           11 :   static Future<void> tearDownTestEnvironment() async {
         120            0 :     if (kDebugMode || TestConfig.instance.isVerboseLogging) {
         121           22 :       debugPrint('EventBus: 테스트 환경 초기화 해제 시작');
         122              :     }
         123              :
         124              :     // 테스트 환경 해제 전 비동기 리소스 상태 로깅
         125           11 :     await _logAsyncResourceState('테스트 환경 해제 전');
         126              :
         127              :     // 테스트 종료 전 남아있는 타이머가 완료될 시간 제공
         128           11 :     await _ensureAllTimersComplete();
         129              :
         130              :     // 현재 테스트 ID에 해당하는 인스턴스가 있는 경우 먼저 dispose 호출
         131           20 :     if (_currentTestId != null && _testInstances.containsKey(_currentTestId!)) {
         132              :       try {
         133            0 :         if (kDebugMode || TestConfig.instance.isVerboseLogging) {
         134           30 :           debugPrint('EventBus: 현재 테스트 ID($_currentTestId) 인스턴스 dispose 시도');
         135              :         }
         136           30 :         await _testInstances[_currentTestId!]!.dispose();
         137              :       } catch (e) {
         138              :         if (kDebugMode) {
         139            0 :           debugPrint('EventBus: 현재 테스트 인스턴스 dispose 중 오류 - $e');
         140              :         }
         141              :       }
         142              :     }
         143              :
         144              :     _currentTestId = null;
         145              :     // 테스트 환경 초기화 해제 로깅
         146              :     _isTestEnvironmentReady = false;
         147              :     if (kDebugMode) {
         148           22 :       debugPrint('EventBus: 테스트 환경 초기화 해제');
         149              :     }
         150              :     _activeSubscriptionCount = 0;
         151              :
         152              :     // 테스트 환경 해제 후 비동기 리소스 상태 로깅
         153           11 :     await _logAsyncResourceState('테스트 환경 해제 후');
         154              :
         155              :     // 메모리 누수 방지를 위해 GC 힌트 추가
         156           11 :     if (TestUtils.isInTest) {
         157            2 :       developer.log('EventBus 메모리 정리 요청', name: 'EventBus');
         158              :     }
         159              :
         160              :     // 추가 마이크로태스크 실행으로 비동기 작업 완료 보장
         161           22 :     await Future.microtask(() {});
         162           22 :     await Future.microtask(() {});
         163              :   }
         164              :
         165              :   // 테스트 ID 초기화 (후방 호환성을 위해 유지)
         166           10 :   static Future<void> clearCurrentTestId() async {
         167              :     // tearDownTestEnvironment로 대체되었지만 후방 호환성을 위해 유지
         168           10 :     await tearDownTestEnvironment();
         169              :   }
         170              :
         171              :   // 모든 테스트 인스턴스를 정리하는 정적 메서드
         172            1 :   static Future<void> resetAllTestInstances() async {
         173            2 :     if (_testInstances.isEmpty) {
         174              :       return;
         175              :     }
         176              :
         177            0 :     if (kDebugMode || TestConfig.instance.isVerboseLogging) {
         178            5 :       debugPrint('EventBus: 모든 테스트 인스턴스 초기화 시작 (인스턴스 수: ${_testInstances.length})');
         179              :     }
         180              :
         181              :     // 초기화 전 비동기 리소스 상태 로깅
         182            1 :     await _logAsyncResourceState('모든 테스트 인스턴스 초기화 전');
         183              :
         184              :     // 기존 인스턴스 모두 정리
         185            3 :     for (var entry in _testInstances.entries) {
         186              :       try {
         187              :         if (kDebugMode) {
         188            4 :           debugPrint('EventBus: 인스턴스 정리 중 - ${entry.key}');
         189              :         }
         190            2 :         entry.value.dispose(); // 완전히 dispose 호출
         191              :
         192              :         // 각 인스턴스 dispose 후 마이크로태스크 실행으로 비동기 작업 완료 보장
         193            2 :         await Future.microtask(() {});
         194              :       } catch (e) {
         195              :         // dispose 중 오류 무시
         196              :         if (kDebugMode) {
         197            0 :           debugPrint('EventBus: 인스턴스 정리 중 오류 - $e');
         198              :         }
         199              :       }
         200              :     }
         201              :
         202              :     // 인스턴스 정리 후 중간 상태 로깅
         203            1 :     await _logAsyncResourceState('테스트 인스턴스 dispose 후, 초기화 전');
         204              :
         205              :     // 모든 테스트 인스턴스 제거
         206            2 :     _testInstances.clear();
         207              :
         208              :     // 기본 인스턴스도 초기화
         209              :     try {
         210            2 :       _instance.reset();
         211            2 :       await Future.microtask(() {}); // 기본 인스턴스 초기화 후 마이크로태스크 실행
         212              :     } catch (e) {
         213              :       // 기본 인스턴스 초기화 중 오류 무시
         214              :       if (kDebugMode) {
         215            0 :         debugPrint('EventBus: 기본 인스턴스 초기화 중 오류 - $e');
         216              :       }
         217              :     }
         218              :
         219              :     // 현재 테스트 ID도 초기화
         220              :     _currentTestId = null;
         221              :     // 테스트 환경 초기화 해제 로깅
         222              :     if (_isTestEnvironmentReady) {
         223              :       _isTestEnvironmentReady = false;
         224              :       if (kDebugMode) {
         225            2 :         debugPrint('EventBus: 모든 테스트 환경 초기화 해제');
         226              :       }
         227              :     }
         228              :     _activeSubscriptionCount = 0;
         229              :
         230              :     // 비동기 작업이 완료될 시간을 제공하되, 타이머 생성 없이 동기화
         231              :     // 타이머 생성 없이 마이크로태스크 큐 완료 보장
         232            2 :     await Future.microtask(() {});
         233            2 :     await Future.microtask(() {});
         234              :
         235              :     // 테스트 종료 전 남아있는 타이머가 완료될 시간 제공
         236              :     // 테스트 환경에서 !timersPending assertion 실패 방지
         237            1 :     await _ensureAllTimersComplete();
         238              :
         239              :     // 초기화 완료 후 비동기 리소스 상태 로깅
         240            1 :     await _logAsyncResourceState('모든 테스트 인스턴스 초기화 후');
         241              :
         242            0 :     if (kDebugMode || TestConfig.instance.isVerboseLogging) {
         243            2 :       debugPrint('EventBus: 모든 테스트 인스턴스 초기화됨');
         244            1 :       developer.log('EventBus 메모리 상태 초기화 완료', name: 'EventBus');
         245              :     }
         246              :   }
         247              :
         248              :   // 비동기 리소스 상태 진단 및 로깅
         249           11 :   static Future<Map<String, dynamic>> _diagnoseAsyncResources() async {
         250           11 :     final diagnosticInfo = <String, dynamic>{
         251           22 :       'timestamp': DateTime.now().toIso8601String(),
         252              :       'activeSubscriptions': _activeSubscriptionCount,
         253           22 :       'testInstances': _testInstances.length,
         254              :       'currentTestId': _currentTestId,
         255              :       'isTestEnvironmentReady': _isTestEnvironmentReady,
         256              :       'testRetryCount': _testRetryCount,
         257              :     };
         258              :
         259              :     // 인스턴스별 상태 수집
         260           11 :     final instanceStates = <String, Map<String, dynamic>>{};
         261           33 :     for (final entry in _testInstances.entries) {
         262           33 :       instanceStates[entry.key] = {
         263           22 :         'isDisposed': entry.value._isDisposed,
         264           33 :         'isStreamControllerClosed': entry.value._streamController.isClosed,
         265              :       };
         266              :     }
         267           11 :     diagnosticInfo['instanceStates'] = instanceStates;
         268              :
         269              :     // 기본 인스턴스 상태
         270           22 :     diagnosticInfo['defaultInstance'] = {
         271           22 :       'isDisposed': _instance._isDisposed,
         272           33 :       'isStreamControllerClosed': _instance._streamController.isClosed,
         273              :     };
         274              :
         275              :     return diagnosticInfo;
         276              :   }
         277              :
         278              :   // 비동기 리소스 상태 로깅
         279           11 :   static Future<void> _logAsyncResourceState(String context) async {
         280            0 :     if (kDebugMode || TestConfig.instance.isVerboseLogging) {
         281           11 :       final diagnosticInfo = await _diagnoseAsyncResources();
         282           33 :       debugPrint('===== EventBus 비동기 리소스 상태 ($context) =====');
         283           44 :       debugPrint('시간: ${diagnosticInfo['timestamp']}');
         284           44 :       debugPrint('활성 구독 수: ${diagnosticInfo['activeSubscriptions']}');
         285           44 :       debugPrint('테스트 인스턴스 수: ${diagnosticInfo['testInstances']}');
         286           44 :       debugPrint('현재 테스트 ID: ${diagnosticInfo['currentTestId']}');
         287           44 :       debugPrint('테스트 환경 준비 상태: ${diagnosticInfo['isTestEnvironmentReady']}');
         288           44 :       debugPrint('테스트 재시도 횟수: ${diagnosticInfo['testRetryCount']}');
         289              :
         290              :       // 인스턴스별 상태 출력
         291           11 :       final instanceStates = diagnosticInfo['instanceStates'] as Map<String, Map<String, dynamic>>;
         292           11 :       if (instanceStates.isNotEmpty) {
         293           22 :         debugPrint('--- 테스트 인스턴스 상태 ---');
         294           22 :         instanceStates.forEach((key, value) {
         295           55 :           debugPrint('  $key: disposed=${value['isDisposed']}, streamClosed=${value['isStreamControllerClosed']}');
         296              :         });
         297              :       }
         298              :
         299              :       // 기본 인스턴스 상태
         300           11 :       final defaultInstance = diagnosticInfo['defaultInstance'] as Map<String, dynamic>;
         301           22 :       debugPrint('--- 기본 인스턴스 상태 ---');
         302           55 :       debugPrint('  disposed=${defaultInstance['isDisposed']}, streamClosed=${defaultInstance['isStreamControllerClosed']}');
         303              :
         304           22 :       debugPrint('===========================================');
         305              :     }
         306              :   }
         307              :
         308           11 :   static Future<void> _ensureAllTimersComplete() async {
         309            0 :     if (kDebugMode || TestConfig.instance.isVerboseLogging) {
         310           22 :       debugPrint('EventBus: 타이머 완료 대기 시작');
         311              :     }
         312              :
         313              :     // 비동기 리소스 상태 로깅 (시작)
         314           11 :     await _logAsyncResourceState('타이머 완료 대기 시작');
         315              :
         316              :     // 타이머를 새로 만들지 않기 위해 microtask만 사용
         317           22 :     await Future.microtask(() {});
         318           22 :     await Future.microtask(() {});
         319           22 :     await Future.microtask(() {});
         320              :
         321              :     // 중간 상태 로깅
         322           11 :     await _logAsyncResourceState('타이머 완료 중간 상태');
         323              :
         324              :     // 테스트 설정에서 정의된 타이머 완료 대기 시간을 적용
         325              :     // 추가 대기 시간이 설정되어 있어도 실제 Timer 생성은 하지 않음(테스트 타이머 경합 방지)
         326              :     // 필요한 경우 호출자에서 fakeAsync 등을 사용해 제어하도록 위임
         327              :
         328              :     // 비동기 리소스 상태 로깅 (완료)
         329           11 :     await _logAsyncResourceState('타이머 완료 대기 완료');
         330              :
         331            0 :     if (kDebugMode || TestConfig.instance.isVerboseLogging) {
         332           22 :       debugPrint('EventBus: 타이머 완료 대기 완료');
         333              :     }
         334              :   }
         335              :
         336           11 :   factory EventBus() {
         337              :     // 테스트 환경에서는 테스트 ID 자동 생성 및 설정
         338           11 :     if (TestUtils.isInTest) {
         339              :       // 테스트 ID가 설정되지 않았다면 자동으로 생성하지 말고, 명시적 설정을 강제한다
         340              :       if (_currentTestId == null) {
         341            0 :         throw StateError('EventBus: 테스트 환경에서 currentTestId가 설정되지 않았습니다. setUp에서 EventBus.setCurrentTestId(...)를 호출하세요.');
         342              :       }
         343              :
         344              :       // 테스트 ID가 있지만 인스턴스가 없는 경우 생성
         345           16 :       if (!_testInstances.containsKey(_currentTestId!)) {
         346              :         if (kDebugMode) {
         347            0 :           debugPrint('EventBus: 테스트 ID ${_currentTestId}에 대한 새 인스턴스 생성');
         348              :         }
         349            0 :         _testInstances[_currentTestId!] = EventBus._internal();
         350            0 :         _testInstances[_currentTestId!]!.reset();
         351              :       }
         352              :
         353           16 :       return _testInstances[_currentTestId]!;
         354              :     }
         355              :
         356              :     // 테스트 환경이 아닌 경우 기본 싱글톤 인스턴스 반환
         357            3 :     return _instance;
         358              :   }
         359              :
         360           15 :   EventBus._internal();
         361              :
         362              :   // 이벤트 버스 내부 상태
         363              :   StreamController _streamController = StreamController.broadcast();
         364              :   bool _isDisposed = false;
         365              :
         366           12 :   Stream get stream => _streamController.stream;
         367              :
         368            4 :   void fire(dynamic event) {
         369           12 :     if (!_isDisposed && !_streamController.isClosed) {
         370            8 :       _streamController.add(event);
         371              :       // 디버그 모드 또는 상세 로깅 설정 시 이벤트 발생 로그 추가
         372            0 :       if (kDebugMode || TestConfig.instance.isVerboseLogging) {
         373           12 :         debugPrint('EventBus: 이벤트 발생 - $event');
         374              :       }
         375            0 :     } else if (kDebugMode || TestConfig.instance.isVerboseLogging) {
         376            0 :       debugPrint('EventBus: 이벤트 발생 실패 (이미 dispose됨) - $event');
         377              :     }
         378              :   }
         379              :
         380              :   // 특정 타입의 이벤트를 구독하는 메서드
         381            4 :   Stream<T> on<T>() {
         382            4 :     if (_isDisposed) {
         383            0 :       if (kDebugMode || TestConfig.instance.isVerboseLogging) {
         384            0 :         debugPrint('EventBus: dispose된 인스턴스에서 on<$T> 호출됨');
         385              :       }
         386              :       // 빈 스트림 반환
         387            0 :       return Stream<T>.empty();
         388              :     }
         389              :
         390              :     // 타입 필터링 및 변환
         391           20 :     final filteredStream = stream.where((event) => event is T).cast<T>();
         392              :
         393              :     // 구독 생성 시 카운터 증가 - 한 번만 증가
         394            4 :     _activeSubscriptionCount++;
         395              :
         396            4 :     if (TestUtils.isInTest) {
         397            0 :       if (kDebugMode || TestConfig.instance.isVerboseLogging) {
         398           12 :         debugPrint('EventBus: 새 구독 추가됨 <$T> (현재 구독 수: $_activeSubscriptionCount)');
         399              :       }
         400              :
         401              :       // 구독 취소 시 카운터 감소를 위한 처리
         402              :       // StreamController를 사용하여 구독 취소 시 카운터 감소 보장
         403            4 :       final controller = StreamController<T>();
         404              :
         405              :       // 원본 스트림에서 데이터 수신 및 전달
         406            4 :       final subscription = filteredStream.listen(
         407            8 :         (data) => controller.add(data),
         408            0 :         onError: (error) => controller.addError(error),
         409            2 :         onDone: () => controller.close(),
         410              :       );
         411              :
         412              :       // 컨트롤러 닫힐 때 구독 취소 및 카운터 감소
         413            8 :       controller.onCancel = () {
         414            4 :         subscription.cancel();
         415            8 :         _activeSubscriptionCount = (_activeSubscriptionCount > 0) ? _activeSubscriptionCount - 1 : 0;
         416            0 :         if (kDebugMode || TestConfig.instance.isVerboseLogging) {
         417           12 :           debugPrint('EventBus: 구독 취소됨 <$T> (남은 구독 수: $_activeSubscriptionCount)');
         418              :         }
         419              :       };
         420              :
         421            4 :       return controller.stream;
         422              :     }
         423              :
         424              :     return filteredStream;
         425              :   }
         426              :
         427           15 :   Future<void> _logInstanceState() async {
         428            0 :     if (kDebugMode || TestConfig.instance.isVerboseLogging) {
         429           30 :       debugPrint('EventBus 인스턴스 상태:');
         430           60 :       debugPrint('  isDisposed: $_isDisposed');
         431           75 :       debugPrint('  streamController.isClosed: ${_streamController.isClosed}');
         432           15 :       if (TestUtils.isInTest) {
         433           21 :         debugPrint('  현재 테스트 ID: $_currentTestId');
         434           21 :         debugPrint('  활성 구독 수: $_activeSubscriptionCount');
         435              :       }
         436              :     }
         437              :   }
         438              :
         439           15 :   Future<void> dispose() async {
         440           15 :     if (!_isDisposed) {
         441              :       // dispose 전 상태 로깅
         442            0 :       if (kDebugMode || TestConfig.instance.isVerboseLogging) {
         443           30 :         debugPrint('EventBus: dispose 시작');
         444           15 :         await _logInstanceState();
         445              :       }
         446              :
         447           15 :       _isDisposed = true;
         448           30 :       if (!_streamController.isClosed) {
         449              :         try {
         450           30 :           await _streamController.close();
         451              :
         452              :           // 마이크로태스크 실행으로 비동기 작업 완료 보장
         453           30 :           await Future.microtask(() {});
         454              :
         455           15 :           if ((kDebugMode || TestConfig.instance.isVerboseLogging) && TestUtils.isInTest) {
         456           21 :             debugPrint('EventBus: 인스턴스 dispose 완료 (테스트 ID: $_currentTestId)');
         457              :             // dispose 후 상태 로깅
         458            7 :             await _logInstanceState();
         459              :           }
         460              :         } catch (e) {
         461            0 :           if (kDebugMode || TestConfig.instance.isVerboseLogging) {
         462            0 :             debugPrint('EventBus: dispose 중 오류 - $e');
         463              :           }
         464              :         }
         465              :       }
         466            0 :     } else if (kDebugMode || TestConfig.instance.isVerboseLogging) {
         467            0 :       debugPrint('EventBus: 이미 dispose된 인스턴스에 dispose 호출됨');
         468              :     }
         469              :   }
         470              :
         471              :   /// 테스트 환경에서 EventBus를 초기화하는 메서드
         472              :   /// 기존 StreamController를 닫고 새로운 것으로 교체
         473            9 :   Future<void> reset() async {
         474            0 :     if (kDebugMode || TestConfig.instance.isVerboseLogging) {
         475           18 :       debugPrint('EventBus: reset 시작');
         476            9 :       await _logInstanceState();
         477              :     }
         478              :
         479            9 :     if (!_isDisposed) {
         480              :       try {
         481            8 :         await dispose();
         482              :       } catch (e) {
         483              :         if (kDebugMode) {
         484            0 :           debugPrint('EventBus: reset 중 dispose 호출 오류 - $e');
         485              :         }
         486              :       }
         487              :     }
         488              :
         489              :     // 새로운 StreamController 생성
         490           18 :     _streamController = StreamController.broadcast();
         491            9 :     _isDisposed = false;
         492              :
         493              :     // 활성 구독 수 초기화 (인스턴스 레벨)
         494            9 :     if (TestUtils.isInTest) {
         495              :       _activeSubscriptionCount = 0;
         496              :     }
         497              :
         498              :     // 마이크로태스크 실행으로 비동기 작업 완료 보장
         499           18 :     await Future.microtask(() {});
         500              :
         501            0 :     if (kDebugMode || TestConfig.instance.isVerboseLogging) {
         502           27 :       debugPrint('EventBus: 인스턴스 reset 완료 (테스트 ID: $_currentTestId)');
         503            9 :       await _logInstanceState();
         504              :     }
         505              :   }
         506              : }

Generated by: LCOV version 2.3.1-1