Files
zszq-trs/UnitTestProject/Modules/SwapModule/TestableSwapFlowEventService.cs
hjhan f0ef37b599 test(swap): SwapFlowEventService seam改造+MergePageEventScenarioTest(6场景全绿)
借鉴 testable 分支,只取 seam(排除 PosiPnl/NetSettmentAmount 公式改动和 MergePageEvent 拆分),
填补当前分支对开平仓合成(MergePageEvent)零覆盖的空白。

SwapFlowEventService 新增11个 protected virtual seam:
- FindTrade/FindTradeExtend/FindPositions/FindAndInvalidateFutureEvents
- GetUnderlying/GetNextBusinessDay/ResolvePositionId
- PersistEvents(替代InitEvent内联Add+SaveChanges)/BeginTransaction/CommitTransaction/RollbackTransaction
MergePageEvent/InitEvent: private→protected virtual,内联DB调用替换为seam。
InitEvent 移除 DbContext.swap_flow_event.Add(转入PersistEvents,纯函数化)。
SwapTradeBaseService.UpdateDbOption: public void→public virtual(测试override用)。

新增测试(借鉴testable分支):
- TestableSwapFlowEventService.cs(集中式共享包装类)
- MergePageEventScenarioTest.cs(6场景全绿):
  Scenario1 单条无持仓开仓 / Scenario2 同向追加 / Scenario3 反向全平
  Scenario4 反向部分平+开 / Scenario5 一开一平 / Scenario6 复杂组合

**未借鉴**:SearchPositionFlowEvent的PosiPnl/NetSettmentAmount公式改动(行为变更)、
MergePageEvent拆分ProcessSingleFlow等(非必需重构)。
SwapModule 169测试全绿(+6),无回归。
2026-07-03 09:26:13 +08:00

94 lines
3.6 KiB
C#

using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using YLErp.DBModels;
using YLErp.DBModels.Enums;
using YLErp.Model;
using YLErp.Modules.SwapModule;
namespace YLErp.Modules.SwapModule
{
/// <summary>
/// 可测试的 SwapFlowEventService 子类
/// override 所有外部依赖方法,用内存数据替代数据库和静态调用
/// </summary>
public class TestableSwapFlowEventService : SwapFlowEventService
{
private readonly trade _trade;
private readonly trade_extend _tradeExtend;
private readonly List<swap_position> _positions;
private readonly Dictionary<string, underlying_manager> _underlyings;
private readonly Func<DateTime, DateTime> _nextBusinessDay;
private readonly long _positionId;
public List<swap_flow_event> PersistedEvents { get; } = new List<swap_flow_event>();
public TestableSwapFlowEventService(
OptUserInfo optUser,
trade trade,
trade_extend tradeExtend,
List<swap_position> positions,
Dictionary<string, underlying_manager> underlyings,
Func<DateTime, DateTime> nextBusinessDay,
long positionId = 999999
) : base(optUser)
{
_trade = trade;
_tradeExtend = tradeExtend;
_positions = positions ?? new List<swap_position>();
_underlyings = underlyings ?? new Dictionary<string, underlying_manager>();
_nextBusinessDay = nextBusinessDay ?? (d => d.AddDays(1));
_positionId = positionId;
}
protected override trade FindTrade(int swapTradeId) => _trade;
protected override trade_extend FindTradeExtend(int swapTradeId) => _tradeExtend;
protected override List<swap_position> FindPositions(int swapTradeId) => _positions;
protected override List<swap_flow_event> FindAndInvalidateFutureEvents(int swapTradeId, DateTime tradeDate)
{
// 测试环境:不需要废弃历史事件
return new List<swap_flow_event>();
}
protected override underlying_manager GetUnderlying(string underlyingCode)
{
return _underlyings.TryGetValue(underlyingCode, out var ul) ? ul : new underlying_manager { UnderlyingCode = underlyingCode };
}
protected override DateTime GetNextBusinessDay(DateTime date) => _nextBusinessDay(date);
protected override long ResolvePositionId(swap_flow_merge merge, DateTime maturityDate, int direction, string tradeNumber) => _positionId;
protected override void PersistEvents(List<swap_flow_event> events)
{
// 不写 DB,收集到列表供验证
PersistedEvents.AddRange(events);
}
protected override IDisposable BeginTransaction() => new NoopDisposable();
protected override void CommitTransaction(IDisposable transaction) { }
protected override void RollbackTransaction(IDisposable transaction) { }
/// <summary>公开调用 protected 的 MergePageEvent,供测试使用</summary>
public List<swap_flow_event> ExecuteMergePageEvent(int swapTradeId, List<swap_flow_merge> flowMergeList, DateTime tradeDate, bool needTrans = false)
{
return MergePageEvent(swapTradeId, flowMergeList, tradeDate, needTrans);
}
public override void UpdateDbOption(DBModelBaseV2 dBModel)
{
// 测试环境不设 Opt 信息,避免依赖 UserInfo
}
private class NoopDisposable : IDisposable
{
public void Dispose() { }
}
}
}