test(health): 扩展患者集成测试 +3 — 更新乐观锁/PII加密验证/姓名搜索
Some checks failed
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
CI / frontend-build (push) Has been cancelled
CI / security-audit (push) Has been cancelled

This commit is contained in:
iven
2026-04-27 21:58:57 +08:00
parent dc09cc4e2a
commit fdbbc47a60

View File

@@ -4,7 +4,7 @@
//! 使用 TestDb 创建隔离 PostgreSQL 数据库,直接调用 service 层函数。 //! 使用 TestDb 创建隔离 PostgreSQL 数据库,直接调用 service 层函数。
use erp_core::events::EventBus; use erp_core::events::EventBus;
use erp_health::dto::patient_dto::CreatePatientReq; use erp_health::dto::patient_dto::{CreatePatientReq, UpdatePatientReq};
use erp_health::service::patient_service; use erp_health::service::patient_service;
use erp_health::state::HealthState; use erp_health::state::HealthState;
use erp_core::crypto::PiiCrypto; use erp_core::crypto::PiiCrypto;
@@ -206,3 +206,114 @@ async fn test_patient_soft_delete() {
let lookup = patient_service::get_patient(&state, tenant_id, patient.id).await; let lookup = patient_service::get_patient(&state, tenant_id, patient.id).await;
assert!(lookup.is_err(), "软删除后查询应返回错误"); assert!(lookup.is_err(), "软删除后查询应返回错误");
} }
#[tokio::test]
async fn test_patient_update_and_optimistic_lock() {
let test_db = TestDb::new().await;
let state = make_state(test_db.db());
let tenant_id = uuid::Uuid::new_v4();
let operator_id = uuid::Uuid::new_v4();
let patient = patient_service::create_patient(&state, tenant_id, Some(operator_id), CreatePatientReq {
name: "更新前".to_string(),
gender: Some("male".to_string()),
birth_date: None, blood_type: None, id_number: None,
allergy_history: None, medical_history_summary: None,
emergency_contact_name: None, emergency_contact_phone: None,
source: None, notes: None,
})
.await
.expect("创建应成功");
// 正确版本更新
let updated = patient_service::update_patient(
&state, tenant_id, patient.id, Some(operator_id),
UpdatePatientReq {
name: Some("更新后".to_string()),
gender: None, birth_date: None, blood_type: None,
id_number: None, allergy_history: None,
medical_history_summary: None, emergency_contact_name: None,
emergency_contact_phone: None, source: None, notes: None,
status: None, verification_status: None,
},
patient.version,
)
.await
.expect("更新应成功");
assert_eq!(updated.name, "更新后");
assert_eq!(updated.version, 2);
// 旧版本更新应失败
let result = patient_service::update_patient(
&state, tenant_id, patient.id, Some(operator_id),
UpdatePatientReq {
name: Some("冲突".to_string()),
gender: None, birth_date: None, blood_type: None,
id_number: None, allergy_history: None,
medical_history_summary: None, emergency_contact_name: None,
emergency_contact_phone: None, source: None, notes: None,
status: None, verification_status: None,
},
patient.version, // 旧版本
)
.await;
assert!(result.is_err(), "旧版本更新应失败");
}
#[tokio::test]
async fn test_patient_pii_encrypted() {
let test_db = TestDb::new().await;
let state = make_state(test_db.db());
let tenant_id = uuid::Uuid::new_v4();
let patient = patient_service::create_patient(&state, tenant_id, None, CreatePatientReq {
name: "加密患者".to_string(),
gender: None,
birth_date: None, blood_type: None,
id_number: Some("330102199001011234".to_string()),
allergy_history: Some("花粉过敏".to_string()),
medical_history_summary: Some("高血压".to_string()),
emergency_contact_name: Some("王五".to_string()),
emergency_contact_phone: Some("13900139000".to_string()),
source: None, notes: None,
})
.await
.expect("创建应成功");
// 列表视图应隐藏 id_number
assert!(patient.id_number.is_none(), "列表视图不应返回身份证号");
// get_patient 详情应包含 PII 解密后的字段(部分脱敏)
let detail = patient_service::get_patient(&state, tenant_id, patient.id)
.await
.expect("查询详情应成功");
// id_number 返回脱敏版本
assert!(detail.id_number.is_some(), "详情应返回 id_number脱敏");
assert_eq!(detail.allergy_history, Some("花粉过敏".to_string()));
assert_eq!(detail.emergency_contact_name, Some("王五".to_string()));
}
#[tokio::test]
async fn test_patient_search_by_name() {
let test_db = TestDb::new().await;
let state = make_state(test_db.db());
let tenant_id = uuid::Uuid::new_v4();
for name in &["赵一", "钱二", "孙三"] {
patient_service::create_patient(&state, tenant_id, None, CreatePatientReq {
name: name.to_string(),
gender: None, birth_date: None, blood_type: None, id_number: None,
allergy_history: None, medical_history_summary: None,
emergency_contact_name: None, emergency_contact_phone: None,
source: None, notes: None,
})
.await
.unwrap();
}
let result = patient_service::list_patients(&state, tenant_id, 1, 10, Some("".to_string()), None)
.await
.expect("搜索应成功");
assert_eq!(result.total, 1);
assert_eq!(result.data[0].name, "钱二");
}