Files
InternalAuditInterprise/backend/tests/integration/test_graph_repo.py
T
2026-06-16 00:38:57 +08:00

77 lines
3.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""知识图谱穿透集成测试(需 PostgreSQL)。
验证 R2 关键能力:通过关系边的多跳穿透识别"疑似同一实控人"
以及本体约束对非法关系的拒绝。对应场景一(政企拆单+隐性实控人,R8)的图谱基础。
"""
from __future__ import annotations
import pytest
from app.datahub.graph_repo import (
OntologyViolationError,
add_relationship,
find_related_entities,
upsert_entity,
)
from app.datahub.ontology import EntityType, RelationshipType
def test_upsert_entity_is_idempotent(session):
e1 = upsert_entity(session, EntityType.CUSTOMER, "CUST-001", "客户甲")
e2 = upsert_entity(session, EntityType.CUSTOMER, "CUST-001", "客户甲")
assert e1.id == e2.id
def test_ontology_violation_rejected(session):
contract = upsert_entity(session, EntityType.CONTRACT, "C-1")
customer = upsert_entity(session, EntityType.CUSTOMER, "CUST-2")
# 合同 —签约→ 客户 方向非法
with pytest.raises(OntologyViolationError):
add_relationship(session, RelationshipType.SIGNED, contract, customer)
def test_detect_shared_controller_across_customers(session):
"""模拟"8 个客户疑似同一实控人":多个客户经法人关联到同一实控自然人。
构图:每个客户 <-法定代表人- 各自法人;各法人 -关联-> 同一实控人。
从实控人出发,应能穿透到全部客户。
"""
controller = upsert_entity(session, EntityType.LEGAL_PERSON, "PER-CTRL", "实控人")
customers = []
for i in range(8):
cust = upsert_entity(session, EntityType.CUSTOMER, f"CUST-{i}", f"政企客户{i}")
rep = upsert_entity(session, EntityType.LEGAL_PERSON, f"PER-{i}", f"法人{i}")
# 法人 —法定代表人→ 客户
add_relationship(session, RelationshipType.LEGAL_REP_OF, rep, cust)
# 法人 —关联(亲属/实控)→ 实控人
add_relationship(session, RelationshipType.RELATED_TO, rep, controller)
customers.append(cust)
session.flush()
related = find_related_entities(session, controller.id, max_depth=3)
related_ids = {rid for rid, _ in related}
# 从实控人 3 跳内应能穿透到全部 8 个客户
for cust in customers:
assert cust.id in related_ids, f"未穿透到 {cust.business_key}"
def test_traversal_respects_max_depth(session):
a = upsert_entity(session, EntityType.LEGAL_PERSON, "A")
b = upsert_entity(session, EntityType.LEGAL_PERSON, "B")
c = upsert_entity(session, EntityType.CUSTOMER, "C")
add_relationship(session, RelationshipType.RELATED_TO, a, b)
add_relationship(session, RelationshipType.LEGAL_REP_OF, b, c)
session.flush()
# depth=1:从 A 只能到 B,到不了 C
ids_d1 = {rid for rid, _ in find_related_entities(session, a.id, max_depth=1)}
assert b.id in ids_d1
assert c.id not in ids_d1
# depth=2:能到 C
ids_d2 = {rid for rid, _ in find_related_entities(session, a.id, max_depth=2)}
assert c.id in ids_d2