246 lines
8.5 KiB
Dart
246 lines
8.5 KiB
Dart
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:timezone/timezone.dart' as tz;
|
|
import 'package:timezone/data/latest.dart' as tz_data;
|
|
import 'package:integration_test/integration_test.dart';
|
|
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
|
import 'package:lanebow/models/event_model.dart';
|
|
import 'package:lanebow/services/notification_service.dart';
|
|
import 'package:mockito/annotations.dart';
|
|
import 'package:mockito/mockito.dart';
|
|
import 'notification_integration_test.mocks.dart';
|
|
|
|
@GenerateMocks([
|
|
FlutterLocalNotificationsPlugin,
|
|
AndroidFlutterLocalNotificationsPlugin,
|
|
IOSFlutterLocalNotificationsPlugin,
|
|
])
|
|
|
|
void main() {
|
|
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
|
|
|
// timezone 초기화
|
|
tz_data.initializeTimeZones();
|
|
|
|
late MockFlutterLocalNotificationsPlugin mockNotificationsPlugin;
|
|
late MockAndroidFlutterLocalNotificationsPlugin mockAndroidPlugin;
|
|
late MockIOSFlutterLocalNotificationsPlugin mockIOSPlugin;
|
|
late NotificationService originalNotificationService;
|
|
|
|
setUp(() {
|
|
// 목 플러그인 생성
|
|
mockNotificationsPlugin = MockFlutterLocalNotificationsPlugin();
|
|
mockAndroidPlugin = MockAndroidFlutterLocalNotificationsPlugin();
|
|
mockIOSPlugin = MockIOSFlutterLocalNotificationsPlugin();
|
|
|
|
// 원래 인스턴스 저장
|
|
originalNotificationService = NotificationService();
|
|
|
|
// 목 플러그인 설정
|
|
when(mockNotificationsPlugin.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>())
|
|
.thenReturn(mockAndroidPlugin);
|
|
when(mockNotificationsPlugin.resolvePlatformSpecificImplementation<IOSFlutterLocalNotificationsPlugin>())
|
|
.thenReturn(mockIOSPlugin);
|
|
|
|
// 권한 요청 목업
|
|
when(mockIOSPlugin.requestPermissions(
|
|
alert: true,
|
|
badge: true,
|
|
sound: true,
|
|
critical: false,
|
|
provisional: false,
|
|
)).thenAnswer((_) async => true);
|
|
|
|
// 알림 예약 목업 - 모든 matcher 제거하고 실제 값만 사용
|
|
when(mockNotificationsPlugin.zonedSchedule(
|
|
0, // 알림 ID
|
|
'알림 제목',
|
|
'알림 내용',
|
|
tz.TZDateTime.now(tz.local).add(const Duration(hours: 1)),
|
|
const NotificationDetails(
|
|
android: AndroidNotificationDetails(
|
|
'event_reminder_channel',
|
|
'이벤트 리마인더',
|
|
channelDescription: '예정된 이벤트에 대한 알림을 표시합니다',
|
|
importance: Importance.high,
|
|
priority: Priority.high,
|
|
),
|
|
iOS: DarwinNotificationDetails(
|
|
presentAlert: true,
|
|
presentBadge: true,
|
|
presentSound: true,
|
|
),
|
|
),
|
|
androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle,
|
|
matchDateTimeComponents: DateTimeComponents.time,
|
|
payload: 'test-payload',
|
|
)).thenAnswer((_) async {});
|
|
|
|
// 테스트용 NotificationService 생성 및 설정
|
|
// 새로 추가한 createTestInstance 메서드를 사용하여 mock 플러그인을 주입
|
|
final testNotificationService = NotificationService.createTestInstance(mockNotificationsPlugin);
|
|
NotificationService.setTestInstance(testNotificationService);
|
|
});
|
|
|
|
tearDown(() {
|
|
// 테스트 후 원래 NotificationService 복원
|
|
NotificationService.setTestInstance(originalNotificationService);
|
|
});
|
|
|
|
group('알림 서비스 통합 테스트', () {
|
|
test('알림 권한 요청 기능이 작동해야 함', () async {
|
|
// NotificationService 테스트 인스턴스 생성 및 설정
|
|
final notificationService = NotificationService();
|
|
NotificationService.setTestInstance(notificationService);
|
|
|
|
// given
|
|
when(mockNotificationsPlugin.initialize(any, onDidReceiveNotificationResponse: anyNamed('onDidReceiveNotificationResponse')))
|
|
.thenAnswer((_) async => true);
|
|
|
|
when(mockIOSPlugin.requestPermissions(
|
|
alert: true,
|
|
badge: true,
|
|
sound: true,
|
|
critical: false,
|
|
provisional: false,
|
|
)).thenAnswer((_) async => true);
|
|
|
|
// when - 위젯 테스트 대신 직접 메서드 호출
|
|
await notificationService.requestPermission();
|
|
|
|
// then - 권한 요청 메서드가 호출되었는지 확인
|
|
verify(mockIOSPlugin.requestPermissions(
|
|
alert: true,
|
|
badge: true,
|
|
sound: true,
|
|
critical: false,
|
|
provisional: false,
|
|
)).called(1);
|
|
});
|
|
|
|
test('이벤트 알림 설정 기능이 작동해야 함', () async {
|
|
// given
|
|
when(mockNotificationsPlugin.initialize(any, onDidReceiveNotificationResponse: anyNamed('onDidReceiveNotificationResponse')))
|
|
.thenAnswer((_) async => true);
|
|
|
|
// 테스트용 이벤트 생성
|
|
final testEvent = Event(
|
|
id: 'test_event_id',
|
|
clubId: 'test_club_id',
|
|
title: '테스트 이벤트',
|
|
description: '테스트 이벤트 설명',
|
|
startDate: DateTime.now().add(const Duration(hours: 2)),
|
|
endDate: DateTime.now().add(const Duration(hours: 4)),
|
|
location: '테스트 장소',
|
|
maxParticipants: 10,
|
|
gameCount: 3,
|
|
participantFee: 10000,
|
|
registrationDeadline: DateTime.now().add(const Duration(days: 2)),
|
|
isActive: true,
|
|
createdBy: 'test_user_id',
|
|
type: '팀전',
|
|
);
|
|
|
|
// NotificationService 테스트 인스턴스 생성 및 설정
|
|
final notificationService = NotificationService();
|
|
NotificationService.setTestInstance(notificationService);
|
|
|
|
// zonedSchedule 메서드 stub 설정 - any matcher 사용
|
|
when(mockNotificationsPlugin.zonedSchedule(
|
|
any,
|
|
any,
|
|
any,
|
|
any,
|
|
any,
|
|
androidScheduleMode: anyNamed('androidScheduleMode'),
|
|
matchDateTimeComponents: anyNamed('matchDateTimeComponents'),
|
|
payload: anyNamed('payload'),
|
|
)).thenAnswer((_) async {});
|
|
|
|
// when - 알림 설정 메서드 직접 호출
|
|
await notificationService.scheduleEventStartReminder(testEvent);
|
|
|
|
// then - zonedSchedule이 호출되었는지 확인
|
|
verify(mockNotificationsPlugin.zonedSchedule(
|
|
any,
|
|
'이벤트 시작 알림',
|
|
'${testEvent.title} 이벤트가 1시간 후에 시작됩니다.',
|
|
any,
|
|
any,
|
|
androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle,
|
|
matchDateTimeComponents: DateTimeComponents.time,
|
|
payload: testEvent.id,
|
|
)).called(1);
|
|
});
|
|
});
|
|
}
|
|
|
|
// 테스트를 위한 NotificationService 확장 클래스
|
|
class TestNotificationService implements NotificationService {
|
|
final FlutterLocalNotificationsPlugin mockNotificationsPlugin;
|
|
bool _isInitialized = false;
|
|
|
|
TestNotificationService(this.mockNotificationsPlugin);
|
|
|
|
FlutterLocalNotificationsPlugin get _notificationsPlugin => mockNotificationsPlugin;
|
|
|
|
@override
|
|
bool get isInitialized => _isInitialized;
|
|
|
|
@override
|
|
set isInitialized(bool value) {
|
|
_isInitialized = value;
|
|
}
|
|
|
|
@override
|
|
Future<void> initialize() async {
|
|
_isInitialized = true;
|
|
return Future.value();
|
|
}
|
|
|
|
@override
|
|
Future<bool> requestPermission() async {
|
|
return Future.value(true);
|
|
}
|
|
|
|
@override
|
|
Future<void> showNotification({required int id, required String title, required String body, String? payload}) {
|
|
return Future.value();
|
|
}
|
|
|
|
@override
|
|
Future<void> scheduleNotification({required int id, required String title, required String body, required DateTime scheduledDate, String? payload}) {
|
|
return Future.value();
|
|
}
|
|
|
|
@override
|
|
Future<void> scheduleEventStartReminder(Event event) {
|
|
return Future.value();
|
|
}
|
|
|
|
@override
|
|
Future<void> scheduleRegistrationDeadlineReminder(Event event) {
|
|
return Future.value();
|
|
}
|
|
|
|
@override
|
|
Future<void> cancelEventNotifications(String eventId) {
|
|
return Future.value();
|
|
}
|
|
|
|
@override
|
|
Future<void> cancelAllNotifications() {
|
|
return Future.value();
|
|
}
|
|
}
|
|
|
|
// NotificationService에 테스트 인스턴스를 설정하기 위한 확장
|
|
extension NotificationServiceTestExtension on NotificationService {
|
|
static void setTestInstance(NotificationService instance) {
|
|
// 이 메서드는 실제 구현에서는 작동하지 않지만, 테스트 목적으로 추가
|
|
// 실제로는 NotificationService 클래스에 이 기능을 추가해야 함
|
|
// 테스트에서는 이 메서드가 호출될 때 NotificationService._instance를 교체하는 방식으로 동작해야 함
|
|
}
|
|
}
|
|
|
|
// MockIOSFlutterLocalNotificationsPlugin은 이제 @GenerateMocks에 의해 자동 생성됩니다.
|