//! erp-health 医生管理集成测试 //! //! 验证医生 CRUD、列表搜索、租户隔离、乐观锁。 use erp_health::dto::doctor_dto::*; use erp_health::service::doctor_service; use super::test_fixture::TestApp; fn default_create_doctor_req() -> CreateDoctorReq { CreateDoctorReq { user_id: None, name: "张三".to_string(), department: Some("肾内科".to_string()), title: Some("主任医师".to_string()), specialty: Some("血液透析".to_string()), license_number: None, bio: None, } } // --------------------------------------------------------------------------- // 测试 1: 创建医生 // --------------------------------------------------------------------------- #[tokio::test] async fn test_doctor_create() { let app = TestApp::new().await; let doctor = doctor_service::create_doctor( app.health_state(), app.tenant_id(), Some(app.operator_id()), default_create_doctor_req(), ) .await .expect("创建医生应成功"); assert_eq!(doctor.name, "张三"); assert_eq!(doctor.department, Some("肾内科".to_string())); assert_eq!(doctor.online_status, "offline"); assert_eq!(doctor.version, 1); } // --------------------------------------------------------------------------- // 测试 2: 查询医生 // --------------------------------------------------------------------------- #[tokio::test] async fn test_doctor_get() { let app = TestApp::new().await; let doctor = doctor_service::create_doctor( app.health_state(), app.tenant_id(), Some(app.operator_id()), default_create_doctor_req(), ) .await .unwrap(); let fetched = doctor_service::get_doctor(app.health_state(), app.tenant_id(), doctor.id) .await .expect("查询应成功"); assert_eq!(fetched.id, doctor.id); assert_eq!(fetched.name, "张三"); } // --------------------------------------------------------------------------- // 测试 3: 更新医生 // --------------------------------------------------------------------------- #[tokio::test] async fn test_doctor_update() { let app = TestApp::new().await; let doctor = doctor_service::create_doctor( app.health_state(), app.tenant_id(), Some(app.operator_id()), default_create_doctor_req(), ) .await .unwrap(); let updated = doctor_service::update_doctor( app.health_state(), app.tenant_id(), doctor.id, Some(app.operator_id()), UpdateDoctorReq { name: Some("李四".to_string()), department: None, title: Some("副主任医师".to_string()), specialty: None, license_number: None, bio: Some("擅长透析治疗".to_string()), online_status: Some("online".to_string()), }, doctor.version, ) .await .expect("更新应成功"); assert_eq!(updated.name, "李四"); assert_eq!(updated.title, Some("副主任医师".to_string())); assert_eq!(updated.online_status, "online"); assert_eq!(updated.version, 2); } // --------------------------------------------------------------------------- // 测试 4: 医生列表 + 搜索 // --------------------------------------------------------------------------- #[tokio::test] async fn test_doctor_list_and_search() { let app = TestApp::new().await; doctor_service::create_doctor( app.health_state(), app.tenant_id(), Some(app.operator_id()), CreateDoctorReq { name: "王医生".to_string(), department: Some("心内科".to_string()), ..default_create_doctor_req() }, ) .await .unwrap(); doctor_service::create_doctor( app.health_state(), app.tenant_id(), Some(app.operator_id()), CreateDoctorReq { name: "赵医生".to_string(), department: Some("肾内科".to_string()), ..default_create_doctor_req() }, ) .await .unwrap(); // 全量列表 let all = doctor_service::list_doctors(app.health_state(), app.tenant_id(), 1, 20, None, None, None) .await .unwrap(); assert_eq!(all.total, 2); // 按科室过滤 let renal = doctor_service::list_doctors( app.health_state(), app.tenant_id(), 1, 20, None, Some("肾内科".to_string()), None, ) .await .unwrap(); assert_eq!(renal.total, 1); } // --------------------------------------------------------------------------- // 测试 5: 医生软删除 // --------------------------------------------------------------------------- #[tokio::test] async fn test_doctor_soft_delete() { let app = TestApp::new().await; let doctor = doctor_service::create_doctor( app.health_state(), app.tenant_id(), Some(app.operator_id()), default_create_doctor_req(), ) .await .unwrap(); doctor_service::delete_doctor( app.health_state(), app.tenant_id(), doctor.id, Some(app.operator_id()), doctor.version, ) .await .expect("删除应成功"); let result = doctor_service::get_doctor(app.health_state(), app.tenant_id(), doctor.id).await; assert!(result.is_err(), "软删除后查询应失败"); } // --------------------------------------------------------------------------- // 测试 6: 租户隔离 // --------------------------------------------------------------------------- #[tokio::test] async fn test_doctor_tenant_isolation() { let app = TestApp::new().await; let doctor = doctor_service::create_doctor( app.health_state(), app.tenant_id(), Some(app.operator_id()), default_create_doctor_req(), ) .await .unwrap(); let other_tenant = uuid::Uuid::new_v4(); let result = doctor_service::get_doctor(app.health_state(), other_tenant, doctor.id).await; assert!(result.is_err(), "不同租户不应看到此医生"); let other_list = doctor_service::list_doctors(app.health_state(), other_tenant, 1, 20, None, None, None) .await .unwrap(); assert_eq!(other_list.total, 0); } // --------------------------------------------------------------------------- // 测试 7: 乐观锁冲突 // --------------------------------------------------------------------------- #[tokio::test] async fn test_doctor_version_conflict() { let app = TestApp::new().await; let doctor = doctor_service::create_doctor( app.health_state(), app.tenant_id(), Some(app.operator_id()), default_create_doctor_req(), ) .await .unwrap(); // 先更新一次 doctor_service::update_doctor( app.health_state(), app.tenant_id(), doctor.id, Some(app.operator_id()), UpdateDoctorReq { name: Some("第一次".to_string()), department: None, title: None, specialty: None, license_number: None, bio: None, online_status: None, }, doctor.version, ) .await .unwrap(); // 用旧 version 再更新应失败 let result = doctor_service::update_doctor( app.health_state(), app.tenant_id(), doctor.id, Some(app.operator_id()), UpdateDoctorReq { name: Some("冲突".to_string()), department: None, title: None, specialty: None, license_number: None, bio: None, online_status: None, }, doctor.version, ) .await; assert!(result.is_err(), "乐观锁冲突应返回错误"); }