- 모든 서비스 메서드 시그니처를 실제 구현에 맞게 수정 - 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
553 lines
20 KiB
Dart
553 lines
20 KiB
Dart
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:get_it/get_it.dart';
|
|
import 'package:superport/data/datasources/remote/api_client.dart';
|
|
import 'package:superport/data/datasources/remote/auth_remote_datasource.dart';
|
|
import 'package:superport/data/datasources/remote/company_remote_datasource.dart';
|
|
import 'package:superport/data/datasources/remote/warehouse_remote_datasource.dart';
|
|
import 'package:superport/data/datasources/remote/equipment_remote_datasource.dart';
|
|
import 'package:superport/services/auth_service.dart';
|
|
import 'package:superport/services/company_service.dart';
|
|
import 'package:superport/services/warehouse_service.dart';
|
|
import 'package:superport/services/equipment_service.dart';
|
|
import 'package:superport/data/models/auth/login_request.dart';
|
|
import 'package:superport/data/models/company/company_dto.dart';
|
|
import 'package:superport/data/models/warehouse/warehouse_dto.dart';
|
|
import 'package:superport/data/models/equipment/equipment_request.dart';
|
|
import 'package:superport/models/equipment_unified_model.dart';
|
|
import 'package:superport/models/company_model.dart';
|
|
import 'package:superport/models/warehouse_location_model.dart';
|
|
import 'package:superport/models/address_model.dart';
|
|
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
|
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
|
|
|
void main() {
|
|
late GetIt getIt;
|
|
late ApiClient apiClient;
|
|
late AuthService authService;
|
|
late CompanyService companyService;
|
|
late WarehouseService warehouseService;
|
|
late EquipmentService equipmentService;
|
|
|
|
// 테스트용 데이터
|
|
late Company testCompany;
|
|
late WarehouseLocation testWarehouse;
|
|
final List<int> createdEquipmentIds = [];
|
|
|
|
setUpAll(() async {
|
|
// GetIt 초기화
|
|
getIt = GetIt.instance;
|
|
await getIt.reset();
|
|
|
|
// 환경 변수 로드
|
|
try {
|
|
await dotenv.load(fileName: '.env');
|
|
} catch (e) {
|
|
// Environment file not found, using defaults
|
|
}
|
|
|
|
// API 클라이언트 설정
|
|
apiClient = ApiClient();
|
|
getIt.registerSingleton<ApiClient>(apiClient);
|
|
|
|
// SecureStorage 설정
|
|
const secureStorage = FlutterSecureStorage();
|
|
getIt.registerSingleton<FlutterSecureStorage>(secureStorage);
|
|
|
|
// DataSource 등록
|
|
getIt.registerLazySingleton<AuthRemoteDataSource>(
|
|
() => AuthRemoteDataSourceImpl(apiClient),
|
|
);
|
|
getIt.registerLazySingleton<CompanyRemoteDataSource>(
|
|
() => CompanyRemoteDataSourceImpl(apiClient),
|
|
);
|
|
getIt.registerLazySingleton<WarehouseRemoteDataSource>(
|
|
() => WarehouseRemoteDataSourceImpl(apiClient: apiClient),
|
|
);
|
|
getIt.registerLazySingleton<EquipmentRemoteDataSource>(
|
|
() => EquipmentRemoteDataSourceImpl(),
|
|
);
|
|
|
|
// Service 등록
|
|
getIt.registerLazySingleton<AuthService>(
|
|
() => AuthServiceImpl(
|
|
getIt<AuthRemoteDataSource>(),
|
|
getIt<FlutterSecureStorage>(),
|
|
),
|
|
);
|
|
getIt.registerLazySingleton<CompanyService>(
|
|
() => CompanyService(getIt<CompanyRemoteDataSource>()),
|
|
);
|
|
getIt.registerLazySingleton<WarehouseService>(
|
|
() => WarehouseService(),
|
|
);
|
|
getIt.registerLazySingleton<EquipmentService>(
|
|
() => EquipmentService(),
|
|
);
|
|
|
|
authService = getIt<AuthService>();
|
|
companyService = getIt<CompanyService>();
|
|
warehouseService = getIt<WarehouseService>();
|
|
equipmentService = getIt<EquipmentService>();
|
|
|
|
// 테스트 계정으로 로그인
|
|
final loginRequest = LoginRequest(
|
|
email: 'admin@superport.kr',
|
|
password: 'admin123!',
|
|
);
|
|
|
|
final loginResult = await authService.login(loginRequest);
|
|
loginResult.fold(
|
|
(failure) => throw Exception('로그인 실패: ${failure.message}'),
|
|
(_) => {},
|
|
);
|
|
|
|
// 테스트용 회사 생성
|
|
final createCompanyRequest = CreateCompanyRequest(
|
|
name: 'Equipment_Test_Company_${DateTime.now().millisecondsSinceEpoch}',
|
|
address: '서울시 강남구 테스트로 123',
|
|
contactName: '테스트 담당자',
|
|
contactPosition: '과장',
|
|
contactPhone: '010-1234-5678',
|
|
contactEmail: 'equipment.test@test.com',
|
|
companyTypes: ['customer'],
|
|
remark: '장비 테스트용 회사',
|
|
);
|
|
|
|
final company = Company(
|
|
name: createCompanyRequest.name,
|
|
address: Address.fromFullAddress(createCompanyRequest.address),
|
|
contactName: createCompanyRequest.contactName,
|
|
contactPosition: createCompanyRequest.contactPosition,
|
|
contactPhone: createCompanyRequest.contactPhone,
|
|
contactEmail: createCompanyRequest.contactEmail,
|
|
companyTypes: [CompanyType.customer],
|
|
remark: createCompanyRequest.remark,
|
|
);
|
|
testCompany = await companyService.createCompany(company);
|
|
// 테스트 회사 생성: ${testCompany.name} (ID: ${testCompany.id})
|
|
|
|
// 테스트용 창고 생성
|
|
final createWarehouseRequest = CreateWarehouseLocationRequest(
|
|
name: 'Equipment_Test_Warehouse_${DateTime.now().millisecondsSinceEpoch}',
|
|
address: '서울시 강남구 창고로 456',
|
|
city: '서울',
|
|
state: '서울특별시',
|
|
postalCode: '12345',
|
|
country: '대한민국',
|
|
capacity: 1000,
|
|
managerId: null,
|
|
);
|
|
|
|
testWarehouse = await warehouseService.createWarehouseLocation(
|
|
WarehouseLocation(
|
|
id: 0, // 임시 ID, 서버에서 할당
|
|
name: createWarehouseRequest.name,
|
|
address: Address(
|
|
zipCode: createWarehouseRequest.postalCode ?? '',
|
|
region: createWarehouseRequest.city ?? '',
|
|
detailAddress: createWarehouseRequest.address ?? '',
|
|
),
|
|
remark: '테스트 창고',
|
|
),
|
|
);
|
|
// 테스트 창고 생성: ${testWarehouse.name} (ID: ${testWarehouse.id})
|
|
});
|
|
|
|
tearDownAll(() async {
|
|
// 생성된 장비 삭제
|
|
for (final id in createdEquipmentIds) {
|
|
try {
|
|
await equipmentService.deleteEquipment(id);
|
|
// 테스트 장비 삭제: ID $id
|
|
} catch (e) {
|
|
// 장비 삭제 실패 (ID: $id): $e
|
|
}
|
|
}
|
|
|
|
// 테스트 창고 삭제
|
|
try {
|
|
await warehouseService.deleteWarehouseLocation(testWarehouse.id);
|
|
// 테스트 창고 삭제: ${testWarehouse.name}
|
|
} catch (e) {
|
|
// 창고 삭제 실패: $e
|
|
}
|
|
|
|
// 테스트 회사 삭제
|
|
try {
|
|
await companyService.deleteCompany(testCompany.id!);
|
|
// 테스트 회사 삭제: ${testCompany.name}
|
|
} catch (e) {
|
|
// 회사 삭제 실패: $e
|
|
}
|
|
|
|
// 로그아웃
|
|
try {
|
|
await authService.logout();
|
|
} catch (e) {
|
|
// 로그아웃 중 오류: $e
|
|
}
|
|
|
|
// GetIt 정리
|
|
await getIt.reset();
|
|
});
|
|
|
|
group('장비 관리 화면 통합 테스트', () {
|
|
test('장비 목록 조회', () async {
|
|
// Act
|
|
final equipments = await equipmentService.getEquipments(
|
|
page: 1,
|
|
perPage: 20,
|
|
);
|
|
|
|
// Assert
|
|
expect(equipments, isNotNull);
|
|
|
|
// 장비 목록 조회 성공: 총 ${equipments.length}개 장비 조회됨
|
|
|
|
if (equipments.isNotEmpty) {
|
|
// 첫 번째 장비: ${equipments.first.name} (${equipments.first.manufacturer})
|
|
}
|
|
});
|
|
|
|
test('장비 입고 (생성)', () async {
|
|
// Arrange
|
|
final equipmentData = CreateEquipmentRequest(
|
|
equipmentNumber: 'EQ-${DateTime.now().millisecondsSinceEpoch}',
|
|
category1: '노트북',
|
|
category2: '비즈니스용',
|
|
manufacturer: '삼성전자',
|
|
modelName: 'Galaxy Book Pro',
|
|
serialNumber: 'SN-${DateTime.now().millisecondsSinceEpoch}',
|
|
purchaseDate: DateTime.now().subtract(Duration(days: 30)),
|
|
purchasePrice: 1500000,
|
|
remark: '테스트 장비',
|
|
);
|
|
|
|
// Act
|
|
final equipment = Equipment(
|
|
manufacturer: equipmentData.manufacturer,
|
|
name: equipmentData.modelName ?? equipmentData.equipmentNumber,
|
|
category: equipmentData.category1 ?? '미분류',
|
|
subCategory: equipmentData.category2 ?? '미분류',
|
|
subSubCategory: equipmentData.category3 ?? '미분류',
|
|
serialNumber: equipmentData.serialNumber,
|
|
quantity: 1,
|
|
inDate: equipmentData.purchaseDate,
|
|
remark: equipmentData.remark,
|
|
);
|
|
|
|
final newEquipment = await equipmentService.createEquipment(equipment);
|
|
|
|
// Assert
|
|
expect(newEquipment, isNotNull);
|
|
expect(newEquipment.id, isNotNull);
|
|
expect(newEquipment.serialNumber, equals(equipmentData.serialNumber));
|
|
expect(newEquipment.name, equals(equipmentData.modelName));
|
|
expect(newEquipment.manufacturer, equals(equipmentData.manufacturer));
|
|
|
|
createdEquipmentIds.add(newEquipment.id!);
|
|
|
|
// 장비 입고 성공
|
|
});
|
|
|
|
test('장비 상세 정보 조회', () async {
|
|
// Arrange - 먼저 장비 생성
|
|
final equipmentData = CreateEquipmentRequest(
|
|
equipmentNumber: 'EQ-${DateTime.now().millisecondsSinceEpoch}',
|
|
category1: '노트북',
|
|
category2: '비즈니스용',
|
|
manufacturer: '삼성전자',
|
|
modelName: 'Galaxy Book Pro',
|
|
serialNumber: 'SN-${DateTime.now().millisecondsSinceEpoch}',
|
|
purchaseDate: DateTime.now().subtract(Duration(days: 30)),
|
|
purchasePrice: 1500000,
|
|
remark: '테스트 장비',
|
|
);
|
|
|
|
final equipment = Equipment(
|
|
manufacturer: equipmentData.manufacturer,
|
|
name: equipmentData.modelName ?? equipmentData.equipmentNumber,
|
|
category: equipmentData.category1 ?? '미분류',
|
|
subCategory: equipmentData.category2 ?? '미분류',
|
|
subSubCategory: equipmentData.category3 ?? '미분류',
|
|
serialNumber: equipmentData.serialNumber,
|
|
quantity: 1,
|
|
inDate: equipmentData.purchaseDate,
|
|
remark: equipmentData.remark,
|
|
);
|
|
|
|
final createdEquipment = await equipmentService.createEquipment(equipment);
|
|
final equipmentId = createdEquipment.id!;
|
|
createdEquipmentIds.add(equipmentId);
|
|
|
|
// Act
|
|
final detailEquipment = await equipmentService.getEquipmentDetail(equipmentId);
|
|
|
|
// Assert
|
|
expect(detailEquipment, isNotNull);
|
|
expect(detailEquipment.id, equals(equipmentId));
|
|
expect(detailEquipment.name, equals(equipmentData.modelName));
|
|
expect(detailEquipment.serialNumber, equals(equipmentData.serialNumber));
|
|
|
|
// 장비 상세 정보 조회 성공
|
|
});
|
|
|
|
test('장비 출고', () async {
|
|
// Arrange - 먼저 장비 생성
|
|
final equipmentData = CreateEquipmentRequest(
|
|
equipmentNumber: 'EQ-${DateTime.now().millisecondsSinceEpoch}',
|
|
category1: '노트북',
|
|
category2: '비즈니스용',
|
|
manufacturer: '삼성전자',
|
|
modelName: 'Galaxy Book Pro',
|
|
serialNumber: 'SN-${DateTime.now().millisecondsSinceEpoch}',
|
|
purchaseDate: DateTime.now().subtract(Duration(days: 30)),
|
|
purchasePrice: 1500000,
|
|
remark: '테스트 장비',
|
|
);
|
|
|
|
final equipment = Equipment(
|
|
manufacturer: equipmentData.manufacturer,
|
|
name: equipmentData.modelName ?? equipmentData.equipmentNumber,
|
|
category: equipmentData.category1 ?? '미분류',
|
|
subCategory: equipmentData.category2 ?? '미분류',
|
|
subSubCategory: equipmentData.category3 ?? '미분류',
|
|
serialNumber: equipmentData.serialNumber,
|
|
quantity: 1,
|
|
inDate: equipmentData.purchaseDate,
|
|
remark: equipmentData.remark,
|
|
);
|
|
|
|
final createdEquipment = await equipmentService.createEquipment(equipment);
|
|
createdEquipmentIds.add(createdEquipment.id!);
|
|
|
|
// 출고 요청 데이터
|
|
// Act
|
|
final outResult = await equipmentService.equipmentOut(
|
|
equipmentId: createdEquipment.id!,
|
|
quantity: 1,
|
|
companyId: testCompany.id!,
|
|
notes: '통합 테스트를 위한 장비 출고',
|
|
);
|
|
|
|
// Assert
|
|
expect(outResult, isNotNull);
|
|
|
|
// 장비 출고 성공
|
|
|
|
// 출고 후 상태 확인
|
|
// Equipment 모델에는 status 필드가 없음
|
|
});
|
|
|
|
test('장비 검색 기능', () async {
|
|
// Arrange - 검색용 장비 생성
|
|
final searchKeyword = 'SEARCH_${DateTime.now().millisecondsSinceEpoch}';
|
|
final equipmentData = CreateEquipmentRequest(
|
|
equipmentNumber: searchKeyword,
|
|
category1: '노트북',
|
|
category2: '비즈니스용',
|
|
manufacturer: '삼성전자',
|
|
modelName: 'SearchModel_$searchKeyword',
|
|
serialNumber: 'SN-${DateTime.now().millisecondsSinceEpoch}',
|
|
purchaseDate: DateTime.now().subtract(Duration(days: 30)),
|
|
purchasePrice: 1500000,
|
|
remark: '테스트 장비',
|
|
);
|
|
|
|
final equipment = Equipment(
|
|
manufacturer: equipmentData.manufacturer,
|
|
name: searchKeyword,
|
|
category: equipmentData.category1 ?? '미분류',
|
|
subCategory: equipmentData.category2 ?? '미분류',
|
|
subSubCategory: equipmentData.category3 ?? '미분류',
|
|
serialNumber: equipmentData.serialNumber,
|
|
quantity: 1,
|
|
inDate: equipmentData.purchaseDate,
|
|
remark: equipmentData.remark,
|
|
);
|
|
|
|
final createdEquipment = await equipmentService.createEquipment(equipment);
|
|
createdEquipmentIds.add(createdEquipment.id!);
|
|
|
|
// Act - 모든 장비 조회
|
|
final searchByNumber = await equipmentService.getEquipments(
|
|
page: 1,
|
|
perPage: 100,
|
|
);
|
|
|
|
// Assert
|
|
expect(searchByNumber, isNotEmpty);
|
|
expect(
|
|
searchByNumber.any((e) => e.name.contains(searchKeyword)),
|
|
true,
|
|
);
|
|
|
|
// 장비 검색 성공: 검색어: $searchKeyword, 결과: ${searchByNumber.length}개
|
|
});
|
|
|
|
test('장비 필터링 기본 테스트', () async {
|
|
// Act - 장비 조회
|
|
final equipments = await equipmentService.getEquipments(
|
|
page: 1,
|
|
perPage: 20,
|
|
);
|
|
|
|
// Assert
|
|
expect(equipments, isNotNull);
|
|
|
|
// 장비 필터링 테스트: 총 ${equipments.length}개
|
|
});
|
|
|
|
test('카테고리별 필터링', () async {
|
|
// Arrange - 특정 카테고리 장비 생성
|
|
final category = '노트북';
|
|
final equipmentData = CreateEquipmentRequest(
|
|
equipmentNumber: 'EQ-${DateTime.now().millisecondsSinceEpoch}',
|
|
category1: 'IT장비',
|
|
category2: '컴퓨터',
|
|
category3: category,
|
|
manufacturer: '삼성전자',
|
|
modelName: 'Galaxy Book Pro',
|
|
serialNumber: 'SN-${DateTime.now().millisecondsSinceEpoch}',
|
|
purchaseDate: DateTime.now().subtract(Duration(days: 30)),
|
|
purchasePrice: 1500000,
|
|
remark: '테스트 장비',
|
|
);
|
|
|
|
final equipment = Equipment(
|
|
manufacturer: equipmentData.manufacturer,
|
|
name: equipmentData.modelName ?? equipmentData.equipmentNumber,
|
|
category: equipmentData.category1 ?? '미분류',
|
|
subCategory: equipmentData.category2 ?? '미분류',
|
|
subSubCategory: equipmentData.category3 ?? '미분류',
|
|
serialNumber: equipmentData.serialNumber,
|
|
quantity: 1,
|
|
inDate: equipmentData.purchaseDate,
|
|
remark: equipmentData.remark,
|
|
);
|
|
|
|
final createdEquipment = await equipmentService.createEquipment(equipment);
|
|
createdEquipmentIds.add(createdEquipment.id!);
|
|
|
|
// Act
|
|
final categoryEquipments = await equipmentService.getEquipments(
|
|
page: 1,
|
|
perPage: 100,
|
|
);
|
|
|
|
// Assert
|
|
expect(
|
|
categoryEquipments.any((e) =>
|
|
e.category == 'IT장비' ||
|
|
e.subCategory == '컴퓨터' ||
|
|
e.subSubCategory == category
|
|
),
|
|
true,
|
|
);
|
|
|
|
// 카테고리별 필터링 성공: 카테고리: $category, 조회 결과: ${categoryEquipments.length}개
|
|
});
|
|
|
|
test('장비 정보 수정', () async {
|
|
// Arrange - 먼저 장비 생성
|
|
final equipmentData = CreateEquipmentRequest(
|
|
equipmentNumber: 'EQ-${DateTime.now().millisecondsSinceEpoch}',
|
|
category1: '노트북',
|
|
category2: '비즈니스용',
|
|
manufacturer: '삼성전자',
|
|
modelName: 'Galaxy Book Pro',
|
|
serialNumber: 'SN-${DateTime.now().millisecondsSinceEpoch}',
|
|
purchaseDate: DateTime.now().subtract(Duration(days: 30)),
|
|
purchasePrice: 1500000,
|
|
remark: '테스트 장비',
|
|
);
|
|
|
|
final equipment = Equipment(
|
|
manufacturer: equipmentData.manufacturer,
|
|
name: equipmentData.modelName ?? equipmentData.equipmentNumber,
|
|
category: equipmentData.category1 ?? '미분류',
|
|
subCategory: equipmentData.category2 ?? '미분류',
|
|
subSubCategory: equipmentData.category3 ?? '미분류',
|
|
serialNumber: equipmentData.serialNumber,
|
|
quantity: 1,
|
|
inDate: equipmentData.purchaseDate,
|
|
remark: equipmentData.remark,
|
|
);
|
|
|
|
final createdEquipment = await equipmentService.createEquipment(equipment);
|
|
createdEquipmentIds.add(createdEquipment.id!);
|
|
|
|
// 수정할 데이터
|
|
final updatedEquipment = Equipment(
|
|
id: createdEquipment.id,
|
|
manufacturer: createdEquipment.manufacturer,
|
|
name: '${createdEquipment.name}_수정됨',
|
|
category: createdEquipment.category,
|
|
subCategory: createdEquipment.subCategory,
|
|
subSubCategory: createdEquipment.subSubCategory,
|
|
serialNumber: createdEquipment.serialNumber,
|
|
quantity: createdEquipment.quantity + 1,
|
|
inDate: createdEquipment.inDate,
|
|
remark: '수정된 비고',
|
|
);
|
|
|
|
// Act
|
|
final result = await equipmentService.updateEquipment(
|
|
createdEquipment.id!,
|
|
updatedEquipment,
|
|
);
|
|
|
|
// Assert
|
|
expect(result.name, equals(updatedEquipment.name));
|
|
expect(result.quantity, equals(updatedEquipment.quantity));
|
|
expect(result.remark, equals(updatedEquipment.remark));
|
|
|
|
// 장비 정보 수정 성공
|
|
});
|
|
|
|
test('대량 장비 입고 성능 테스트', () async {
|
|
// Arrange
|
|
final stopwatch = Stopwatch()..start();
|
|
final batchSize = 5;
|
|
final createdIds = <int>[];
|
|
|
|
// Act - 5개 장비 동시 생성
|
|
for (int i = 0; i < batchSize; i++) {
|
|
final equipmentData = CreateEquipmentRequest(
|
|
equipmentNumber: 'BATCH_${DateTime.now().millisecondsSinceEpoch}_$i',
|
|
category1: '노트북',
|
|
category2: '비즈니스용',
|
|
manufacturer: '삼성전자',
|
|
modelName: 'Galaxy Book Pro',
|
|
serialNumber: 'SN-BATCH-${DateTime.now().millisecondsSinceEpoch}_$i',
|
|
purchaseDate: DateTime.now().subtract(Duration(days: 30)),
|
|
purchasePrice: 1500000,
|
|
remark: '대량 테스트 장비 $i',
|
|
);
|
|
|
|
final equipment = Equipment(
|
|
manufacturer: equipmentData.manufacturer,
|
|
name: equipmentData.modelName ?? equipmentData.equipmentNumber,
|
|
category: equipmentData.category1 ?? '미분류',
|
|
subCategory: equipmentData.category2 ?? '미분류',
|
|
subSubCategory: equipmentData.category3 ?? '미분류',
|
|
serialNumber: equipmentData.serialNumber,
|
|
quantity: 1,
|
|
inDate: equipmentData.purchaseDate,
|
|
remark: equipmentData.remark,
|
|
);
|
|
|
|
final created = await equipmentService.createEquipment(equipment);
|
|
createdIds.add(created.id!);
|
|
createdEquipmentIds.add(created.id!);
|
|
}
|
|
|
|
stopwatch.stop();
|
|
|
|
// Assert
|
|
expect(createdIds.length, equals(batchSize));
|
|
|
|
// 대량 장비 입고 성능 테스트 완료
|
|
});
|
|
});
|
|
} |