test: 통합 테스트 오류 및 경고 수정
- 모든 서비스 메서드 시그니처를 실제 구현에 맞게 수정 - TestDataGenerator 제거하고 직접 객체 생성으로 변경 - 모델 필드명 및 타입 불일치 수정 - 불필요한 Either 패턴 사용 제거 - null safety 관련 이슈 해결 수정된 파일: - test/integration/screens/company_integration_test.dart - test/integration/screens/equipment_integration_test.dart - test/integration/screens/user_integration_test.dart - test/integration/screens/login_integration_test.dart
This commit is contained in:
292
test/integration/equipment_in_demo_test.dart
Normal file
292
test/integration/equipment_in_demo_test.dart
Normal file
@@ -0,0 +1,292 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:superport/models/equipment_unified_model.dart';
|
||||
import 'package:superport/data/models/equipment/equipment_response.dart';
|
||||
import 'package:superport/data/models/equipment/equipment_io_response.dart';
|
||||
import 'package:superport/data/models/company/company_dto.dart';
|
||||
import 'package:superport/data/models/warehouse/warehouse_dto.dart';
|
||||
import '../helpers/simple_mock_services.mocks.dart';
|
||||
import '../helpers/simple_mock_services.dart';
|
||||
import '../helpers/mock_data_helpers.dart';
|
||||
|
||||
// AutoFixer import
|
||||
import '../integration/automated/framework/core/auto_fixer.dart';
|
||||
import '../integration/automated/framework/core/api_error_diagnostics.dart';
|
||||
import '../integration/automated/framework/models/error_models.dart';
|
||||
|
||||
/// 장비 입고 데모 테스트
|
||||
///
|
||||
/// 이 테스트는 에러 자동 진단 및 수정 기능을 데모합니다.
|
||||
void main() {
|
||||
late MockEquipmentService mockEquipmentService;
|
||||
late MockCompanyService mockCompanyService;
|
||||
late MockWarehouseService mockWarehouseService;
|
||||
late ApiAutoFixer autoFixer;
|
||||
late ApiErrorDiagnostics diagnostics;
|
||||
|
||||
setUpAll(() {
|
||||
// GetIt 초기화
|
||||
GetIt.instance.reset();
|
||||
});
|
||||
|
||||
setUp(() {
|
||||
mockEquipmentService = MockEquipmentService();
|
||||
mockCompanyService = MockCompanyService();
|
||||
mockWarehouseService = MockWarehouseService();
|
||||
|
||||
// 자동 수정 시스템 초기화
|
||||
diagnostics = ApiErrorDiagnostics();
|
||||
autoFixer = ApiAutoFixer(diagnostics: diagnostics);
|
||||
|
||||
// Mock 서비스 기본 설정
|
||||
SimpleMockServiceHelpers.setupCompanyServiceMock(mockCompanyService);
|
||||
SimpleMockServiceHelpers.setupWarehouseServiceMock(mockWarehouseService);
|
||||
SimpleMockServiceHelpers.setupEquipmentServiceMock(mockEquipmentService);
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
GetIt.instance.reset();
|
||||
});
|
||||
|
||||
group('장비 입고 성공 시나리오', () {
|
||||
test('정상적인 장비 입고 프로세스', () async {
|
||||
// Given: 정상적인 테스트 데이터
|
||||
const testCompanyId = 1;
|
||||
const testWarehouseId = 1;
|
||||
final testEquipment = Equipment(
|
||||
manufacturer: 'Samsung',
|
||||
name: 'Galaxy Book Pro',
|
||||
category: '노트북',
|
||||
subCategory: '업무용',
|
||||
subSubCategory: '고성능',
|
||||
serialNumber: 'SN123456',
|
||||
quantity: 1,
|
||||
);
|
||||
|
||||
// When: 테스트 실행
|
||||
print('\n=== 정상적인 장비 입고 프로세스 시작 ===');
|
||||
|
||||
// 1. 회사 확인
|
||||
print('\n[1단계] 회사 정보 확인');
|
||||
final company = await mockCompanyService.getCompanyDetail(testCompanyId);
|
||||
print('✅ 회사 조회 성공: ${company.name} (ID: ${company.id})');
|
||||
|
||||
// 2. 창고 확인
|
||||
print('\n[2단계] 창고 정보 확인');
|
||||
final warehouse = await mockWarehouseService.getWarehouseLocationById(testWarehouseId);
|
||||
print('✅ 창고 조회 성공: ${warehouse.name} (ID: ${warehouse.id})');
|
||||
|
||||
// 3. 장비 생성
|
||||
print('\n[3단계] 장비 생성');
|
||||
final createdEquipment = await mockEquipmentService.createEquipment(testEquipment);
|
||||
print('✅ 장비 생성 성공: ${createdEquipment.name} (ID: ${createdEquipment.id})');
|
||||
|
||||
// 4. 장비 입고
|
||||
print('\n[4단계] 장비 입고');
|
||||
final inResult = await mockEquipmentService.equipmentIn(
|
||||
equipmentId: createdEquipment.id!,
|
||||
quantity: 1,
|
||||
warehouseLocationId: testWarehouseId,
|
||||
notes: '테스트 입고',
|
||||
);
|
||||
|
||||
print('✅ 장비 입고 성공!');
|
||||
print(' - 트랜잭션 ID: ${inResult.transactionId}');
|
||||
print(' - 장비 ID: ${inResult.equipmentId}');
|
||||
print(' - 수량: ${inResult.quantity}');
|
||||
print(' - 타입: ${inResult.transactionType}');
|
||||
print(' - 메시지: ${inResult.message}');
|
||||
|
||||
// Then: 검증
|
||||
expect(inResult.success, isTrue);
|
||||
expect(inResult.transactionType, equals('IN'));
|
||||
expect(inResult.quantity, equals(1));
|
||||
});
|
||||
});
|
||||
|
||||
group('에러 자동 진단 및 수정 데모', () {
|
||||
test('필수 필드 누락 시 자동 수정', () async {
|
||||
print('\n=== 에러 자동 진단 및 수정 데모 시작 ===');
|
||||
|
||||
// Given: 필수 필드가 누락된 장비 (manufacturer가 비어있음)
|
||||
final incompleteEquipment = Equipment(
|
||||
manufacturer: '', // 빈 제조사 - 에러 발생
|
||||
name: 'Test Equipment',
|
||||
category: '노트북',
|
||||
subCategory: '업무용',
|
||||
subSubCategory: '일반',
|
||||
quantity: 1,
|
||||
);
|
||||
|
||||
// Mock이 특정 에러를 던지도록 설정
|
||||
when(mockEquipmentService.createEquipment(any))
|
||||
.thenThrow(DioException(
|
||||
requestOptions: RequestOptions(path: '/equipment'),
|
||||
response: Response(
|
||||
requestOptions: RequestOptions(path: '/equipment'),
|
||||
statusCode: 400,
|
||||
data: {
|
||||
'error': 'VALIDATION_ERROR',
|
||||
'message': 'Required field missing: manufacturer',
|
||||
'field': 'manufacturer'
|
||||
},
|
||||
),
|
||||
type: DioExceptionType.badResponse,
|
||||
));
|
||||
|
||||
print('\n[1단계] 불완전한 장비 생성 시도');
|
||||
print(' - 제조사: ${incompleteEquipment.manufacturer} (비어있음)');
|
||||
print(' - 이름: ${incompleteEquipment.name}');
|
||||
|
||||
try {
|
||||
await mockEquipmentService.createEquipment(incompleteEquipment);
|
||||
} catch (e) {
|
||||
if (e is DioException) {
|
||||
print('\n❌ 예상된 에러 발생!');
|
||||
print(' - 상태 코드: ${e.response?.statusCode}');
|
||||
print(' - 에러 메시지: ${e.response?.data['message']}');
|
||||
print(' - 문제 필드: ${e.response?.data['field']}');
|
||||
|
||||
// 에러 진단
|
||||
print('\n[2단계] 에러 자동 진단 시작...');
|
||||
final apiError = ApiError(
|
||||
originalError: e,
|
||||
requestUrl: e.requestOptions.path,
|
||||
requestMethod: e.requestOptions.method,
|
||||
statusCode: e.response?.statusCode,
|
||||
serverMessage: e.response?.data['message'],
|
||||
requestBody: incompleteEquipment.toJson(),
|
||||
);
|
||||
|
||||
final diagnosis = await diagnostics.diagnoseError(apiError);
|
||||
print('\n📋 진단 결과:');
|
||||
print(' - 에러 타입: ${diagnosis.type}');
|
||||
print(' - 심각도: ${diagnosis.severity}');
|
||||
print(' - 누락된 필드: ${diagnosis.missingFields}');
|
||||
print(' - 자동 수정 가능: ${diagnosis.isAutoFixable ? "예" : "아니오"}');
|
||||
|
||||
if (diagnosis.isAutoFixable) {
|
||||
// 자동 수정 시도
|
||||
print('\n[3단계] 자동 수정 시작...');
|
||||
final fixResult = await autoFixer.attemptAutoFix(diagnosis);
|
||||
|
||||
if (fixResult.success) {
|
||||
print('\n✅ 자동 수정 성공!');
|
||||
print(' - 수정 ID: ${fixResult.fixId}');
|
||||
print(' - 실행된 액션 수: ${fixResult.executedActions.length}');
|
||||
print(' - 소요 시간: ${fixResult.duration}ms');
|
||||
|
||||
// 수정된 데이터로 재시도
|
||||
final fixedEquipment = Equipment(
|
||||
manufacturer: '미지정', // 자동으로 기본값 설정
|
||||
name: incompleteEquipment.name,
|
||||
category: incompleteEquipment.category,
|
||||
subCategory: incompleteEquipment.subCategory,
|
||||
subSubCategory: incompleteEquipment.subSubCategory,
|
||||
quantity: incompleteEquipment.quantity,
|
||||
);
|
||||
|
||||
// Mock이 수정된 요청에는 성공하도록 설정
|
||||
when(mockEquipmentService.createEquipment(argThat(
|
||||
predicate<Equipment>((eq) => eq.manufacturer.isNotEmpty),
|
||||
))).thenAnswer((_) async => MockDataHelpers.createMockEquipmentModel(
|
||||
id: DateTime.now().millisecondsSinceEpoch,
|
||||
manufacturer: '미지정',
|
||||
name: fixedEquipment.name,
|
||||
));
|
||||
|
||||
print('\n[4단계] 수정된 데이터로 재시도');
|
||||
print(' - 제조사: ${fixedEquipment.manufacturer} (자동 설정됨)');
|
||||
|
||||
final createdEquipment = await mockEquipmentService.createEquipment(fixedEquipment);
|
||||
print('\n✅ 장비 생성 성공!');
|
||||
print(' - ID: ${createdEquipment.id}');
|
||||
print(' - 제조사: ${createdEquipment.manufacturer}');
|
||||
print(' - 이름: ${createdEquipment.name}');
|
||||
|
||||
expect(createdEquipment, isNotNull);
|
||||
expect(createdEquipment.manufacturer, isNotEmpty);
|
||||
} else {
|
||||
print('\n❌ 자동 수정 실패');
|
||||
print(' - 에러: ${fixResult.error}');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test('API 서버 연결 실패 시 재시도', () async {
|
||||
print('\n=== API 서버 연결 실패 재시도 데모 ===');
|
||||
|
||||
var attemptCount = 0;
|
||||
|
||||
// 처음 2번은 실패, 3번째는 성공하도록 설정
|
||||
when(mockEquipmentService.createEquipment(any)).thenAnswer((_) async {
|
||||
attemptCount++;
|
||||
if (attemptCount < 3) {
|
||||
print('\n❌ 시도 $attemptCount: 서버 연결 실패');
|
||||
throw DioException(
|
||||
requestOptions: RequestOptions(path: '/equipment'),
|
||||
type: DioExceptionType.connectionTimeout,
|
||||
message: 'Connection timeout',
|
||||
);
|
||||
} else {
|
||||
print('\n✅ 시도 $attemptCount: 서버 연결 성공!');
|
||||
return MockDataHelpers.createMockEquipmentModel();
|
||||
}
|
||||
});
|
||||
|
||||
final equipment = Equipment(
|
||||
manufacturer: 'Samsung',
|
||||
name: 'Test Equipment',
|
||||
category: '노트북',
|
||||
subCategory: '업무용',
|
||||
subSubCategory: '일반',
|
||||
quantity: 1,
|
||||
);
|
||||
|
||||
print('[1단계] 장비 생성 시도 (네트워크 불안정 상황 시뮬레이션)');
|
||||
|
||||
Equipment? createdEquipment;
|
||||
for (int i = 1; i <= 3; i++) {
|
||||
try {
|
||||
createdEquipment = await mockEquipmentService.createEquipment(equipment);
|
||||
break;
|
||||
} catch (e) {
|
||||
if (i == 3) rethrow;
|
||||
await Future.delayed(Duration(seconds: 1)); // 재시도 전 대기
|
||||
}
|
||||
}
|
||||
|
||||
expect(createdEquipment, isNotNull);
|
||||
expect(attemptCount, equals(3));
|
||||
});
|
||||
});
|
||||
|
||||
group('자동 수정 통계', () {
|
||||
test('수정 이력 및 통계 확인', () async {
|
||||
print('\n=== 자동 수정 통계 ===');
|
||||
|
||||
// 여러 에러 시나리오 실행 후 통계 확인
|
||||
final stats = autoFixer.getSuccessStatistics();
|
||||
|
||||
print('\n📊 자동 수정 통계:');
|
||||
print(' - 총 시도 횟수: ${stats['totalAttempts']}');
|
||||
print(' - 성공한 수정: ${stats['successfulFixes']}');
|
||||
print(' - 성공률: ${(stats['successRate'] * 100).toStringAsFixed(1)}%');
|
||||
print(' - 학습된 패턴 수: ${stats['learnedPatterns']}');
|
||||
print(' - 평균 수정 시간: ${stats['averageFixDuration']}');
|
||||
|
||||
// 수정 이력 확인
|
||||
final history = autoFixer.getFixHistory();
|
||||
if (history.isNotEmpty) {
|
||||
print('\n📜 최근 수정 이력:');
|
||||
for (final fix in history.take(5)) {
|
||||
print(' - ${fix.timestamp}: ${fix.fixResult.fixId} (${fix.action})');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user