Files
zszq-trs/UnitTestProject/Modules/SwapModule/TestableSwapEodPositionService.cs
T
hjhan 4916f7207d test(refactor): SwapInterestScenario3And4 诚实化——去掉 return 0m, 从交易开始日逐日真实收盘
- 删除 StubSwapDealService.GetConsumedInterest 的  硬编码(此前注释明写"与生产缺陷态一致",
  等于把唯一会出错的机制整个屏蔽, 断言缺陷态输出, 伪绿)。
- 改为复用生产同一口径: 对真实收盘经 PersistFlowEvent 累积的 swap_flow_event
  (EventType∈{互换,自动互换}, DataState=完成, EventDate<结算日) 求和 —— 数据来自真实代码执行, 非硬编码。
- TestableSwapEodPositionService 新增 FlowEvents 捕获 + override PersistFlowEvent, 供 GetConsumedInterest 真实计算(不连库)。
- 新增 E2EEodService: 从交易开始日(TradeDate)逐日驱动真实 SwapPositionCompose 构建 eod 链,
  再把真实 eod 快照喂给平仓; 平仓走生产同一入口 SaveAutoEodWithCloseInterestPosition。
- 全程无硬编码输入: FR007 曲线/名义本金/日期均来自 Excel 场景真源, 计算全走真实代码。
- 验证: 24/24 通过(SKIP_INITIALIZATION); PrepaidPrincipal 追踪测试 2/2 通过; 基类改动无回归。
- 注: ConsumedInterestScenarioTest.CI_008 既有失败(复利重置日本金继承, 与本回合无关, 未触碰该文件), 另议。
2026-08-09 11:22:42 +08:00

88 lines
3.9 KiB
C#
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.
using YLErp.DBModels;
using YLErp.DBModels.Enums;
using YLErp.Model;
namespace YLErp.Modules.SwapModule
{
/// <summary>
/// SwapEodPositionService 的可测试化基类(纯内存,不连库)。
/// ============================================================================
/// 收敛各 ScenarioTest 中 Stub 子类的重复 override
/// - PersistEodSwapPosition:收集到列表,不写库
/// - SaveAllChangesno-op
/// - GetCurrencyRate:返回 1.0(本币)
/// - 统一构造函数(注入 OptUserInfo,标记 UnitTest 来源)
///
/// 暴露 PersistedPositions / SaveChangesCount / ClientCashCalls 等输出捕获属性,
/// 供断言使用。各测试子类按需再 override 业务 seamFindTrade/GetUnderlyingPrice 等)。
///
/// 设计原则:
/// - 只收敛 8/8 Stub 都重复的高频 override,不预设业务数据注入方式
/// ComposePage 用属性字典、SwapPositionCompose 用构造函数 List,差异留给子类)
/// - 不提供 Execute* 包装器(签名各异且大多只出现 1-2 次,留在各子类避免基类膨胀)
/// ============================================================================
/// </summary>
public class TestableSwapEodPositionService : SwapEodPositionService
{
/// <summary>捕获所有持久化的 eod 持仓(按调用顺序)</summary>
public List<eod_swap_position> PersistedPositions { get; } = new();
/// <summary>
/// 捕获所有持久化的互换流水事件(按调用顺序)。
/// 生产 PersistFlowEvent 写 DbContext.swap_flow_eventGetConsumedInterest 也读同一张表。
/// 测试不连库,这里把真实收盘产生的 swap_flow_event 收集起来,
/// 使 GetConsumedInterest 能像生产一样从"真实累积的流水"里算已结利息,
/// 而无需硬编码、无需连库。这是消除"return 0m"伪绿的关键。
/// </summary>
public List<swap_flow_event> FlowEvents { get; } = new();
/// <summary>SaveAllChanges 调用次数</summary>
public int SaveChangesCount { get; private set; }
/// <summary>AddClientCash 调用记录(金额, 操作)</summary>
public List<(double amount, string action)> ClientCashCalls { get; } = new();
/// <summary>自增 id 模拟器(新增 eod 时分配 id</summary>
private int _nextId = 1;
protected TestableSwapEodPositionService(string testName)
: base(new OptUserInfo(0, testName ?? nameof(TestableSwapEodPositionService), OptUserFrom.UnitTest))
{
}
// ===== 高频 seam override8/8 Stub 都重复,收敛到基类)=====
protected override void PersistEodSwapPosition(eod_swap_position position)
{
if (position.id == 0) position.id = _nextId++;
PersistedPositions.Add(position);
}
/// <summary>
/// 捕获真实收盘产生的 swap_flow_event(生产写 DbContext.swap_flow_event)。
/// 与 PersistEodSwapPosition 同理,这里只收集不写库,供 GetConsumedInterest 真实计算。
/// </summary>
protected override void PersistFlowEvent(swap_flow_event flowEvent)
{
if (flowEvent.id == 0) flowEvent.id = _nextId++;
FlowEvents.Add(flowEvent);
}
protected override void SaveAllChanges()
{
SaveChangesCount++;
}
protected override double GetCurrencyRate(string quoteCurrency, string settlementCurrency, DateTime valueDate, bool seekPreday, CurrencyRateType currencyRateType)
{
return 1.0; // 本币,汇率=1
}
protected override int AddClientCash(trade td, double amount, string action, DateTime valueDate)
{
ClientCashCalls.Add((amount, action));
return _nextId++;
}
}
}