"""参数快照(时点化取值)测试。 守的是:覆盖链与兜底 —— 一旦取错维度(如企业户取到市政阈值行) 或漏兜底,核算会用错口径或直接崩溃;同日多次变更必须取最新留痕。 仓储 SQL 的排序语义(同日取 id 最大)在集成测试中覆盖。 """ from dataclasses import FrozenInstanceError from datetime import date from fractions import Fraction import pytest from app.services.param_service import ParamSnapshot def _snap(rows: list[tuple[str, str, str]]) -> ParamSnapshot: """构造快照。rows 须模拟仓储输出:同一 (code, dim) 的最新值在前。""" return ParamSnapshot.from_rows(date(2026, 10, 1), rows) class TestCoverChain: """覆盖链:角色维度 > 产品类别维度 > 默认行('')。""" def test_产品类别维度优先于默认行(self) -> None: snap = _snap([("enterprise.rate", "", "3"), ("enterprise.rate", "municipal_water", "2")]) assert snap.get("enterprise.rate", product_category="municipal_water") == "2" def test_无匹配维度时落默认行(self) -> None: snap = _snap([("enterprise.rate", "", "3"), ("enterprise.rate", "municipal_water", "2")]) assert snap.get("enterprise.rate", product_category="rail_transit") == "3" def test_角色维度优先于产品类别维度(self) -> None: snap = _snap([("some.param", "municipal_water", "A"), ("some.param", "salesperson", "B")]) got = snap.get("some.param", role_code="salesperson", product_category="municipal_water") assert got == "B" def test_无任何维度匹配且无默认行_回退注册表默认值(self) -> None: snap = _snap([("enterprise.rate", "municipal_water", "2")]) # 轨交无行、无默认行 → 回退注册表 default_value(3) assert snap.fraction("enterprise.rate", product_category="rail_transit") == Fraction(3) class TestFallback: """注册表默认值兜底(种子缺失时的安全网)。""" def test_未定义参数按注册表默认值兜底(self) -> None: snap = _snap([]) assert snap.fraction("prepay.rate") == Fraction(10) def test_未注册编码抛ValueError_属代码缺陷(self) -> None: snap = _snap([]) with pytest.raises(ValueError): snap.fraction("not.registered.code") class TestSameDayChanges: """同日多次变更:仓储 SQL 已按 (effective_date, id) 倒序,快照取先出现者。""" def test_同日多次变更取最新一条(self) -> None: snap = _snap([("enterprise.rate", "", "3"), ("enterprise.rate", "", "2")]) assert snap.fraction("enterprise.rate") == Fraction(3) class TestTypedGetters: """类型化取值:Fraction 精确解析、整数、布尔、文本。""" def test_fraction精确解析分数式(self) -> None: snap = _snap([("salesperson.rate.slope", "salesperson", "4/360")]) assert snap.fraction("salesperson.rate.slope", role_code="salesperson") == Fraction(1, 90) def test_integer(self) -> None: snap = _snap([("salesperson.days.boundary", "salesperson", "360")]) assert snap.integer("salesperson.days.boundary", role_code="salesperson") == 360 def test_text返回枚举原文(self) -> None: snap = _snap([("payment.weight.mode", "", "FULL")]) assert snap.text("payment.weight.mode") == "FULL" def test_boolean(self) -> None: snap = _snap([("some.flag", "", "1")]) assert snap.boolean("some.flag") is True assert snap.boolean("some.flag") is not False class TestImmutability: """快照冻结:解析结果不得被调用方改写(核算期间一致性)。""" def test_字段不可赋值(self) -> None: snap = _snap([]) with pytest.raises(FrozenInstanceError): snap.biz_date = date(2026, 1, 1) # type: ignore[misc]