借鉴 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),无回归。
94 lines
3.6 KiB
C#
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() { }
|
|
}
|
|
}
|
|
}
|