68 lines
2.4 KiB
Python
68 lines
2.4 KiB
Python
"""真实 MySQL 只读验证:fin_* 只读查询层可执行,且只发出 SELECT。
|
|||
|
|
|
||
|
|
不写入任何 fin_* 表(模型层本身也不提供写能力)。
|
||
|
|
"""
|
||
|
|
|
||
|
|
from typing import Any
|
||
|
|
|
||
|
|
import pytest
|
||
|
|
from sqlalchemy import event
|
||
|
|
|
||
|
|
from app.infrastructure.db import SessionFactory, engine
|
||
|
|
from app.repository.fund_query_repository import (
|
||
|
|
CustomerScope,
|
||
|
|
FundQueryRepository,
|
||
|
|
PageRequest,
|
||
|
|
)
|
||
|
|
|
||
|
|
# 依赖真实 MySQL:必须打 integration marker,否则按 marker 过滤时会漏测这批用例。
|
||
|
|
pytestmark = pytest.mark.integration
|
||
|
|
|
||
|
|
|
||
|
|
async def test_fund_query_repository_only_issues_select_on_real_mysql() -> None:
|
||
|
|
statements: list[str] = []
|
||
|
|
|
||
|
|
def record(
|
||
|
|
conn: Any, cursor: Any, statement: str, parameters: Any, context: Any, executemany: bool
|
||
|
|
) -> None:
|
||
|
|
statements.append(statement.strip().split()[0].upper())
|
||
|
|
|
||
|
|
event.listen(engine.sync_engine, "before_cursor_execute", record)
|
||
|
|
try:
|
||
|
|
async with SessionFactory() as session:
|
||
|
|
repository = FundQueryRepository(session, scope=CustomerScope.unrestricted())
|
||
|
|
pages = [
|
||
|
|
await repository.products(page=PageRequest(limit=5)),
|
||
|
|
await repository.market_prices(),
|
||
|
|
await repository.nav_history(),
|
||
|
|
await repository.fee_rules(),
|
||
|
|
await repository.accounts(),
|
||
|
|
await repository.cash_ledger(),
|
||
|
|
await repository.capital_flows(),
|
||
|
|
await repository.orders(),
|
||
|
|
await repository.transactions(),
|
||
|
|
await repository.holdings(),
|
||
|
|
await repository.customer_profiles(),
|
||
|
|
await repository.risk_assessments(),
|
||
|
|
await repository.risk_alerts(),
|
||
|
|
await repository.risk_notifications(),
|
||
|
|
]
|
||
|
|
finally:
|
||
|
|
event.remove(engine.sync_engine, "before_cursor_execute", record)
|
||
|
|
|
||
|
|
assert len(pages) == 14
|
||
|
|
assert pages[0].limit == 5
|
||
|
|
assert statements
|
||
|
|
assert set(statements) == {"SELECT"}
|
||
|
|
|
||
|
|
|
||
|
|
async def test_denied_scope_returns_no_customer_rows_on_real_mysql() -> None:
|
||
|
|
async with SessionFactory() as session:
|
||
|
|
repository = FundQueryRepository(session, scope=CustomerScope.denied())
|
||
|
|
holdings = await repository.holdings()
|
||
|
|
transactions = await repository.transactions()
|
||
|
|
|
||
|
|
assert holdings.items == ()
|
||
|
|
assert transactions.items == ()
|
||
|
|
assert holdings.has_more is False
|