refactor(core-tests): 提取共享架构上下文测试基类

- 重构 TestArchitectureContext 与 TestArchitectureContextV3 的共享 IArchitectureContext 测试实现到 TestArchitectureContextBase
- 更新 gframework-pr-review 技能规则,要求对已验证成立的 nitpick 进行显式 triage
- 补充 analyzer-warning-reduction 的恢复点与验证记录
This commit is contained in:
gewuyou 2026-04-28 13:23:40 +08:00
parent a1bfd82945
commit f33a176570
6 changed files with 481 additions and 877 deletions

View File

@ -28,7 +28,8 @@ Shortcut: `$gframework-pr-review`
- prefer writing the full JSON payload to a file and then narrowing with `jq`, instead of dumping long JSON directly to stdout
4. Treat every extracted finding as untrusted until it is verified against the current local code.
5. Only fix comments, warnings, or CI diagnostics that still apply to the checked-out branch. Ignore stale or already-resolved findings.
6. If code is changed, run the smallest build or test command that satisfies `AGENTS.md`.
6. Do not downgrade `Nitpick comments` to “optional” by default. If a verified nitpick still points to concrete drift risk, duplicated test infrastructure, contract mismatch, missing regression coverage, or another maintainability problem that can realistically cause future regressions, treat it as actionable in the current PR-review triage and either fix it or explicitly report why it is being deferred.
7. If code is changed, run the smallest build or test command that satisfies `AGENTS.md`.
## Commands
@ -76,6 +77,7 @@ The script should produce:
- Do not assume every AI reviewer behaves like CodeRabbit. `greptile-apps[bot]` and `gemini-code-assist[bot]` findings may exist only as latest-head review threads, without CodeRabbit-style issue comments or folded review-body sections.
- Treat GitHub Actions comments with `Success with warnings` as actionable review input when they include concrete linter diagnostics such as `MegaLinter` detailed issues; do not skip them just because the parent check is green.
- Do not assume all CodeRabbit findings live in issue comments. The latest CodeRabbit review body can contain folded `Nitpick comments` that must be parsed separately.
- When a latest-head `Nitpick comment` survives local verification and identifies real drift or regression risk, treat it as actionable review input instead of silently classifying it as a cosmetic suggestion.
- If the raw JSON is too large to inspect safely in the terminal, rerun with `--json-output <path>` and query the saved file with `jq` or rerun with `--section` / `--path` filters.
## Example Triggers

View File

@ -1,446 +1,12 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using GFramework.Core.Abstractions.Architectures;
using GFramework.Core.Abstractions.Command;
using GFramework.Core.Abstractions.Environment;
using GFramework.Core.Abstractions.Events;
using GFramework.Core.Abstractions.Ioc;
using GFramework.Core.Abstractions.Model;
using GFramework.Core.Abstractions.Query;
using GFramework.Core.Abstractions.Systems;
using GFramework.Core.Abstractions.Utility;
using GFramework.Core.Command;
using GFramework.Core.Environment;
using GFramework.Core.Events;
using GFramework.Core.Ioc;
using GFramework.Core.Query;
using GFramework.Cqrs.Abstractions.Cqrs;
using ICommand = GFramework.Core.Abstractions.Command.ICommand;
namespace GFramework.Core.Tests.Architectures;
/// <summary>
/// 为 <see cref="GameContextTests" /> 提供最小可用的架构上下文测试桩。
/// </summary>
/// <remarks>
/// 该类型只实现当前测试切片会触达的基础行为,其余 CQRS 入口显式抛出 <see cref="NotSupportedException" />
/// 避免测试误把未覆盖能力当成可用实现
/// 共享的容器解析、事件总线协作与 legacy CQRS 失败契约由 <see cref="TestArchitectureContextBase" /> 提供,
/// 当前类型仅作为默认测试上下文命名入口,供现有测试与派生替身继续复用。
/// </remarks>
public class TestArchitectureContext : IArchitectureContext
public class TestArchitectureContext : TestArchitectureContextBase
{
private readonly MicrosoftDiContainer _container = new();
private readonly EventBus _eventBus = new();
/// <summary>
/// 获取用于解析测试服务的依赖注入容器。
/// </summary>
public IIocContainer Container => _container;
/// <summary>
/// 获取测试事件总线实例。
/// </summary>
/// <remarks>
/// 返回同一个缓存事件总线,以便 <see cref="RegisterEvent{TEvent}" />、<see cref="SendEvent{TEvent}()" /> 与
/// <see cref="UnRegisterEvent{TEvent}" /> 在同一份订阅状态上协作。
/// </remarks>
public IEventBus EventBus => _eventBus;
/// <summary>
/// 获取测试命令执行器实例。
/// </summary>
public ICommandExecutor CommandExecutor => new CommandExecutor();
/// <summary>
/// 获取测试查询执行器实例。
/// </summary>
public IQueryExecutor QueryExecutor => new QueryExecutor();
/// <summary>
/// 获取默认测试环境对象。
/// </summary>
public IEnvironment Environment => new DefaultEnvironment();
/// <summary>
/// 获取指定类型的服务实例。
/// </summary>
/// <typeparam name="TService">服务类型。</typeparam>
/// <returns>已注册的服务实例。</returns>
/// <exception cref="InvalidOperationException">未注册服务时抛出。</exception>
public TService GetService<TService>() where TService : class
{
return _container.GetRequired<TService>();
}
/// <summary>
/// 获取指定类型的所有服务实例。
/// </summary>
/// <typeparam name="TService">服务类型。</typeparam>
/// <returns>服务实例列表。</returns>
public IReadOnlyList<TService> GetServices<TService>() where TService : class
{
return _container.GetAll<TService>();
}
/// <summary>
/// 获取指定类型的模型实例。
/// </summary>
/// <typeparam name="TModel">模型类型。</typeparam>
/// <returns>已注册的模型实例。</returns>
/// <exception cref="InvalidOperationException">未注册模型时抛出。</exception>
public TModel GetModel<TModel>() where TModel : class, IModel
{
return _container.GetRequired<TModel>();
}
/// <summary>
/// 获取指定类型的所有模型实例。
/// </summary>
/// <typeparam name="TModel">模型类型。</typeparam>
/// <returns>模型实例列表。</returns>
public IReadOnlyList<TModel> GetModels<TModel>() where TModel : class, IModel
{
return _container.GetAll<TModel>();
}
/// <summary>
/// 获取指定类型的系统实例。
/// </summary>
/// <typeparam name="TSystem">系统类型。</typeparam>
/// <returns>已注册的系统实例。</returns>
/// <exception cref="InvalidOperationException">未注册系统时抛出。</exception>
public TSystem GetSystem<TSystem>() where TSystem : class, ISystem
{
return _container.GetRequired<TSystem>();
}
/// <summary>
/// 获取指定类型的所有系统实例。
/// </summary>
/// <typeparam name="TSystem">系统类型。</typeparam>
/// <returns>系统实例列表。</returns>
public IReadOnlyList<TSystem> GetSystems<TSystem>() where TSystem : class, ISystem
{
return _container.GetAll<TSystem>();
}
/// <summary>
/// 获取指定类型的工具实例。
/// </summary>
/// <typeparam name="TUtility">工具类型。</typeparam>
/// <returns>已注册的工具实例。</returns>
/// <exception cref="InvalidOperationException">未注册工具时抛出。</exception>
public virtual TUtility GetUtility<TUtility>() where TUtility : class, IUtility
{
return _container.GetRequired<TUtility>();
}
/// <summary>
/// 获取指定类型的所有工具实例。
/// </summary>
/// <typeparam name="TUtility">工具类型。</typeparam>
/// <returns>工具实例列表。</returns>
public IReadOnlyList<TUtility> GetUtilities<TUtility>() where TUtility : class, IUtility
{
return _container.GetAll<TUtility>();
}
/// <summary>
/// 获取指定类型的所有服务实例,并按优先级排序。
/// </summary>
/// <typeparam name="TService">服务类型。</typeparam>
/// <returns>按优先级排序后的服务实例列表。</returns>
public IReadOnlyList<TService> GetServicesByPriority<TService>() where TService : class
{
return _container.GetAllByPriority<TService>();
}
/// <summary>
/// 获取指定类型的所有系统实例,并按优先级排序。
/// </summary>
/// <typeparam name="TSystem">系统类型。</typeparam>
/// <returns>按优先级排序后的系统实例列表。</returns>
public IReadOnlyList<TSystem> GetSystemsByPriority<TSystem>() where TSystem : class, ISystem
{
return _container.GetAllByPriority<TSystem>();
}
/// <summary>
/// 获取指定类型的所有模型实例,并按优先级排序。
/// </summary>
/// <typeparam name="TModel">模型类型。</typeparam>
/// <returns>按优先级排序后的模型实例列表。</returns>
public IReadOnlyList<TModel> GetModelsByPriority<TModel>() where TModel : class, IModel
{
return _container.GetAllByPriority<TModel>();
}
/// <summary>
/// 获取指定类型的所有工具实例,并按优先级排序。
/// </summary>
/// <typeparam name="TUtility">工具类型。</typeparam>
/// <returns>按优先级排序后的工具实例列表。</returns>
public IReadOnlyList<TUtility> GetUtilitiesByPriority<TUtility>() where TUtility : class, IUtility
{
return _container.GetAllByPriority<TUtility>();
}
/// <summary>
/// 发送无参数事件。
/// </summary>
/// <typeparam name="TEvent">事件类型。</typeparam>
public void SendEvent<TEvent>() where TEvent : new()
{
_eventBus.Send<TEvent>();
}
/// <summary>
/// 发送带参数事件。
/// </summary>
/// <typeparam name="TEvent">事件类型。</typeparam>
/// <param name="e">事件实例。</param>
public void SendEvent<TEvent>(TEvent e) where TEvent : class
{
ArgumentNullException.ThrowIfNull(e);
_eventBus.Send(e);
}
/// <summary>
/// 注册事件处理器。
/// </summary>
/// <typeparam name="TEvent">事件类型。</typeparam>
/// <param name="handler">事件处理委托。</param>
/// <returns>用于测试的事件注销句柄。</returns>
public IUnRegister RegisterEvent<TEvent>(Action<TEvent> handler)
{
ArgumentNullException.ThrowIfNull(handler);
return _eventBus.Register(handler);
}
/// <summary>
/// 取消注册事件处理器。
/// </summary>
/// <typeparam name="TEvent">事件类型。</typeparam>
/// <param name="onEvent">事件处理委托。</param>
public void UnRegisterEvent<TEvent>(Action<TEvent> onEvent)
{
ArgumentNullException.ThrowIfNull(onEvent);
_eventBus.UnRegister(onEvent);
}
/// <summary>
/// 测试桩:异步发送统一 CQRS 请求。
/// </summary>
/// <typeparam name="TResponse">响应类型。</typeparam>
/// <param name="request">要发送的请求。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>请求响应任务。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持此成员。</exception>
public ValueTask<TResponse> SendRequestAsync<TResponse>(
IRequest<TResponse> request,
CancellationToken cancellationToken = default)
{
throw new NotSupportedException();
}
/// <summary>
/// 测试桩:同步发送统一 CQRS 请求。
/// </summary>
/// <typeparam name="TResponse">响应类型。</typeparam>
/// <param name="request">要发送的请求。</param>
/// <returns>请求响应。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持此成员。</exception>
public TResponse SendRequest<TResponse>(IRequest<TResponse> request)
{
throw new NotSupportedException();
}
/// <summary>
/// 测试桩:异步发送 CQRS 命令并返回响应。
/// </summary>
/// <typeparam name="TResponse">命令响应类型。</typeparam>
/// <param name="command">要发送的命令。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>命令响应任务。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持此成员。</exception>
public ValueTask<TResponse> SendCommandAsync<TResponse>(
GFramework.Cqrs.Abstractions.Cqrs.Command.ICommand<TResponse> command,
CancellationToken cancellationToken = default)
{
throw new NotSupportedException();
}
/// <summary>
/// 测试桩:同步发送 CQRS 命令并返回响应。
/// </summary>
/// <typeparam name="TResponse">命令响应类型。</typeparam>
/// <param name="command">要发送的命令。</param>
/// <returns>命令响应。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持此成员。</exception>
public TResponse SendCommand<TResponse>(GFramework.Cqrs.Abstractions.Cqrs.Command.ICommand<TResponse> command)
{
throw new NotSupportedException();
}
/// <summary>
/// 测试桩:异步发送 CQRS 查询并返回结果。
/// </summary>
/// <typeparam name="TResponse">查询结果类型。</typeparam>
/// <param name="query">要发送的查询。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>查询结果任务。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持此成员。</exception>
public ValueTask<TResponse> SendQueryAsync<TResponse>(
GFramework.Cqrs.Abstractions.Cqrs.Query.IQuery<TResponse> query,
CancellationToken cancellationToken = default)
{
throw new NotSupportedException();
}
/// <summary>
/// 测试桩:同步发送 CQRS 查询并返回结果。
/// </summary>
/// <typeparam name="TResponse">查询结果类型。</typeparam>
/// <param name="query">要发送的查询。</param>
/// <returns>查询结果。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持此成员。</exception>
public TResponse SendQuery<TResponse>(GFramework.Cqrs.Abstractions.Cqrs.Query.IQuery<TResponse> query)
{
throw new NotSupportedException();
}
/// <summary>
/// 测试桩:异步发布 CQRS 通知。
/// </summary>
/// <typeparam name="TNotification">通知类型。</typeparam>
/// <param name="notification">要发布的通知。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>通知发布任务。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持此成员。</exception>
public ValueTask PublishAsync<TNotification>(
TNotification notification,
CancellationToken cancellationToken = default) where TNotification : INotification
{
throw new NotSupportedException();
}
/// <summary>
/// 测试桩:创建 CQRS 流式请求响应序列。
/// </summary>
/// <typeparam name="TResponse">流式响应元素类型。</typeparam>
/// <param name="request">流式请求。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>异步响应流。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持此成员。</exception>
public IAsyncEnumerable<TResponse> CreateStream<TResponse>(
IStreamRequest<TResponse> request,
CancellationToken cancellationToken = default)
{
throw new NotSupportedException();
}
/// <summary>
/// 测试桩:异步发送无返回值 CQRS 命令。
/// </summary>
/// <typeparam name="TCommand">命令类型。</typeparam>
/// <param name="command">要发送的命令。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>命令发送任务。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持此成员。</exception>
public ValueTask SendAsync<TCommand>(TCommand command, CancellationToken cancellationToken = default)
where TCommand : IRequest<Unit>
{
throw new NotSupportedException();
}
/// <summary>
/// 测试桩:异步发送带返回值的 CQRS 请求。
/// </summary>
/// <typeparam name="TResponse">响应类型。</typeparam>
/// <param name="command">要发送的请求。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>请求响应任务。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持此成员。</exception>
public ValueTask<TResponse> SendAsync<TResponse>(
IRequest<TResponse> command,
CancellationToken cancellationToken = default)
{
throw new NotSupportedException();
}
/// <summary>
/// 发送旧版命令。
/// </summary>
/// <param name="command">命令对象。</param>
/// <exception cref="NotSupportedException">该测试桩不支持旧版命令执行入口。</exception>
public void SendCommand(ICommand command)
{
throw new NotSupportedException();
}
/// <summary>
/// 发送旧版带返回值命令。
/// </summary>
/// <typeparam name="TResult">返回值类型。</typeparam>
/// <param name="command">命令对象。</param>
/// <returns>此方法始终抛出异常,不返回结果。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持旧版命令执行入口。</exception>
public TResult SendCommand<TResult>(ICommand<TResult> command)
{
throw new NotSupportedException();
}
/// <summary>
/// 异步发送旧版命令。
/// </summary>
/// <param name="command">命令对象。</param>
/// <returns>已失败的任务。</returns>
public Task SendCommandAsync(IAsyncCommand command)
{
return Task.FromException(new NotSupportedException());
}
/// <summary>
/// 异步发送旧版带返回值命令。
/// </summary>
/// <typeparam name="TResult">返回值类型。</typeparam>
/// <param name="command">命令对象。</param>
/// <returns>已失败的任务。</returns>
public Task<TResult> SendCommandAsync<TResult>(IAsyncCommand<TResult> command)
{
return Task.FromException<TResult>(new NotSupportedException());
}
/// <summary>
/// 发送旧版查询请求。
/// </summary>
/// <typeparam name="TResult">查询结果类型。</typeparam>
/// <param name="query">查询对象。</param>
/// <returns>此方法始终抛出异常,不返回结果。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持旧版查询执行入口。</exception>
public TResult SendQuery<TResult>(IQuery<TResult> query)
{
throw new NotSupportedException();
}
/// <summary>
/// 异步发送旧版查询请求。
/// </summary>
/// <typeparam name="TResult">查询结果类型。</typeparam>
/// <param name="query">异步查询对象。</param>
/// <returns>已失败的任务。</returns>
public Task<TResult> SendQueryAsync<TResult>(IAsyncQuery<TResult> query)
{
return Task.FromException<TResult>(new NotSupportedException());
}
/// <summary>
/// 获取当前环境对象。
/// </summary>
/// <returns>默认测试环境对象。</returns>
public IEnvironment GetEnvironment()
{
return Environment;
}
}

View File

@ -0,0 +1,451 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using GFramework.Core.Abstractions.Architectures;
using GFramework.Core.Abstractions.Command;
using GFramework.Core.Abstractions.Environment;
using GFramework.Core.Abstractions.Events;
using GFramework.Core.Abstractions.Ioc;
using GFramework.Core.Abstractions.Model;
using GFramework.Core.Abstractions.Query;
using GFramework.Core.Abstractions.Systems;
using GFramework.Core.Abstractions.Utility;
using GFramework.Core.Command;
using GFramework.Core.Environment;
using GFramework.Core.Events;
using GFramework.Core.Ioc;
using GFramework.Core.Query;
using GFramework.Cqrs.Abstractions.Cqrs;
using ICommand = GFramework.Core.Abstractions.Command.ICommand;
namespace GFramework.Core.Tests.Architectures;
/// <summary>
/// 为架构相关测试替身提供共享的 <see cref="IArchitectureContext" /> 基础实现。
/// </summary>
/// <remarks>
/// 该基类统一维护容器解析、共享 <see cref="EventBus" /> 语义,以及 legacy / CQRS 入口的显式失败契约,
/// 以避免多个测试上下文因为并行复制实现而在后续演进中发生语义漂移。
/// </remarks>
public abstract class TestArchitectureContextBase : IArchitectureContext
{
private readonly MicrosoftDiContainer _container = new();
private readonly DefaultEnvironment _environment = new();
private readonly EventBus _eventBus = new();
/// <summary>
/// 获取用于解析测试服务的依赖注入容器。
/// </summary>
public IIocContainer Container => _container;
/// <summary>
/// 获取测试事件总线实例。
/// </summary>
/// <remarks>
/// 返回同一个缓存事件总线,以便 <see cref="RegisterEvent{TEvent}" />、<see cref="SendEvent{TEvent}()" /> 与
/// <see cref="UnRegisterEvent{TEvent}" /> 在同一份订阅状态上协作。
/// </remarks>
public IEventBus EventBus => _eventBus;
/// <summary>
/// 获取测试命令执行器实例。
/// </summary>
public ICommandExecutor CommandExecutor => new CommandExecutor();
/// <summary>
/// 获取测试查询执行器实例。
/// </summary>
public IQueryExecutor QueryExecutor => new QueryExecutor();
/// <summary>
/// 获取默认测试环境对象。
/// </summary>
public IEnvironment Environment => _environment;
/// <summary>
/// 获取指定类型的服务实例。
/// </summary>
/// <typeparam name="TService">服务类型。</typeparam>
/// <returns>已注册的服务实例。</returns>
/// <exception cref="InvalidOperationException">未注册服务时抛出。</exception>
public TService GetService<TService>() where TService : class
{
return _container.GetRequired<TService>();
}
/// <summary>
/// 获取指定类型的所有服务实例。
/// </summary>
/// <typeparam name="TService">服务类型。</typeparam>
/// <returns>服务实例列表。</returns>
public IReadOnlyList<TService> GetServices<TService>() where TService : class
{
return _container.GetAll<TService>();
}
/// <summary>
/// 获取指定类型的模型实例。
/// </summary>
/// <typeparam name="TModel">模型类型。</typeparam>
/// <returns>已注册的模型实例。</returns>
/// <exception cref="InvalidOperationException">未注册模型时抛出。</exception>
public TModel GetModel<TModel>() where TModel : class, IModel
{
return _container.GetRequired<TModel>();
}
/// <summary>
/// 获取指定类型的所有模型实例。
/// </summary>
/// <typeparam name="TModel">模型类型。</typeparam>
/// <returns>模型实例列表。</returns>
public IReadOnlyList<TModel> GetModels<TModel>() where TModel : class, IModel
{
return _container.GetAll<TModel>();
}
/// <summary>
/// 获取指定类型的系统实例。
/// </summary>
/// <typeparam name="TSystem">系统类型。</typeparam>
/// <returns>已注册的系统实例。</returns>
/// <exception cref="InvalidOperationException">未注册系统时抛出。</exception>
public TSystem GetSystem<TSystem>() where TSystem : class, ISystem
{
return _container.GetRequired<TSystem>();
}
/// <summary>
/// 获取指定类型的所有系统实例。
/// </summary>
/// <typeparam name="TSystem">系统类型。</typeparam>
/// <returns>系统实例列表。</returns>
public IReadOnlyList<TSystem> GetSystems<TSystem>() where TSystem : class, ISystem
{
return _container.GetAll<TSystem>();
}
/// <summary>
/// 获取指定类型的工具实例。
/// </summary>
/// <typeparam name="TUtility">工具类型。</typeparam>
/// <returns>已注册的工具实例。</returns>
/// <exception cref="InvalidOperationException">未注册工具时抛出。</exception>
public virtual TUtility GetUtility<TUtility>() where TUtility : class, IUtility
{
return _container.GetRequired<TUtility>();
}
/// <summary>
/// 获取指定类型的所有工具实例。
/// </summary>
/// <typeparam name="TUtility">工具类型。</typeparam>
/// <returns>工具实例列表。</returns>
public IReadOnlyList<TUtility> GetUtilities<TUtility>() where TUtility : class, IUtility
{
return _container.GetAll<TUtility>();
}
/// <summary>
/// 获取指定类型的所有服务实例,并按优先级排序。
/// </summary>
/// <typeparam name="TService">服务类型。</typeparam>
/// <returns>按优先级排序后的服务实例列表。</returns>
public IReadOnlyList<TService> GetServicesByPriority<TService>() where TService : class
{
return _container.GetAllByPriority<TService>();
}
/// <summary>
/// 获取指定类型的所有系统实例,并按优先级排序。
/// </summary>
/// <typeparam name="TSystem">系统类型。</typeparam>
/// <returns>按优先级排序后的系统实例列表。</returns>
public IReadOnlyList<TSystem> GetSystemsByPriority<TSystem>() where TSystem : class, ISystem
{
return _container.GetAllByPriority<TSystem>();
}
/// <summary>
/// 获取指定类型的所有模型实例,并按优先级排序。
/// </summary>
/// <typeparam name="TModel">模型类型。</typeparam>
/// <returns>按优先级排序后的模型实例列表。</returns>
public IReadOnlyList<TModel> GetModelsByPriority<TModel>() where TModel : class, IModel
{
return _container.GetAllByPriority<TModel>();
}
/// <summary>
/// 获取指定类型的所有工具实例,并按优先级排序。
/// </summary>
/// <typeparam name="TUtility">工具类型。</typeparam>
/// <returns>按优先级排序后的工具实例列表。</returns>
public IReadOnlyList<TUtility> GetUtilitiesByPriority<TUtility>() where TUtility : class, IUtility
{
return _container.GetAllByPriority<TUtility>();
}
/// <summary>
/// 发送无参数事件。
/// </summary>
/// <typeparam name="TEvent">事件类型。</typeparam>
public void SendEvent<TEvent>() where TEvent : new()
{
_eventBus.Send<TEvent>();
}
/// <summary>
/// 发送带参数事件。
/// </summary>
/// <typeparam name="TEvent">事件类型。</typeparam>
/// <param name="e">事件实例。</param>
/// <exception cref="ArgumentNullException"><paramref name="e" /> 为 <see langword="null" />。</exception>
public void SendEvent<TEvent>(TEvent e) where TEvent : class
{
ArgumentNullException.ThrowIfNull(e);
_eventBus.Send(e);
}
/// <summary>
/// 注册事件处理器。
/// </summary>
/// <typeparam name="TEvent">事件类型。</typeparam>
/// <param name="handler">事件处理委托。</param>
/// <returns>用于测试的事件注销句柄。</returns>
/// <exception cref="ArgumentNullException"><paramref name="handler" /> 为 <see langword="null" />。</exception>
public IUnRegister RegisterEvent<TEvent>(Action<TEvent> handler)
{
ArgumentNullException.ThrowIfNull(handler);
return _eventBus.Register(handler);
}
/// <summary>
/// 取消注册事件处理器。
/// </summary>
/// <typeparam name="TEvent">事件类型。</typeparam>
/// <param name="onEvent">事件处理委托。</param>
/// <exception cref="ArgumentNullException"><paramref name="onEvent" /> 为 <see langword="null" />。</exception>
public void UnRegisterEvent<TEvent>(Action<TEvent> onEvent)
{
ArgumentNullException.ThrowIfNull(onEvent);
_eventBus.UnRegister(onEvent);
}
/// <summary>
/// 测试桩:异步发送统一 CQRS 请求。
/// </summary>
/// <typeparam name="TResponse">响应类型。</typeparam>
/// <param name="request">要发送的请求。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>请求响应任务。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持此成员。</exception>
public ValueTask<TResponse> SendRequestAsync<TResponse>(
IRequest<TResponse> request,
CancellationToken cancellationToken = default)
{
throw new NotSupportedException();
}
/// <summary>
/// 测试桩:同步发送统一 CQRS 请求。
/// </summary>
/// <typeparam name="TResponse">响应类型。</typeparam>
/// <param name="request">要发送的请求。</param>
/// <returns>请求响应。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持此成员。</exception>
public TResponse SendRequest<TResponse>(IRequest<TResponse> request)
{
throw new NotSupportedException();
}
/// <summary>
/// 测试桩:异步发送 CQRS 命令并返回响应。
/// </summary>
/// <typeparam name="TResponse">命令响应类型。</typeparam>
/// <param name="command">要发送的命令。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>命令响应任务。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持此成员。</exception>
public ValueTask<TResponse> SendCommandAsync<TResponse>(
GFramework.Cqrs.Abstractions.Cqrs.Command.ICommand<TResponse> command,
CancellationToken cancellationToken = default)
{
throw new NotSupportedException();
}
/// <summary>
/// 测试桩:同步发送 CQRS 命令并返回响应。
/// </summary>
/// <typeparam name="TResponse">命令响应类型。</typeparam>
/// <param name="command">要发送的命令。</param>
/// <returns>命令响应。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持此成员。</exception>
public TResponse SendCommand<TResponse>(GFramework.Cqrs.Abstractions.Cqrs.Command.ICommand<TResponse> command)
{
throw new NotSupportedException();
}
/// <summary>
/// 测试桩:异步发送 CQRS 查询并返回结果。
/// </summary>
/// <typeparam name="TResponse">查询结果类型。</typeparam>
/// <param name="query">要发送的查询。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>查询结果任务。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持此成员。</exception>
public ValueTask<TResponse> SendQueryAsync<TResponse>(
GFramework.Cqrs.Abstractions.Cqrs.Query.IQuery<TResponse> query,
CancellationToken cancellationToken = default)
{
throw new NotSupportedException();
}
/// <summary>
/// 测试桩:同步发送 CQRS 查询并返回结果。
/// </summary>
/// <typeparam name="TResponse">查询结果类型。</typeparam>
/// <param name="query">要发送的查询。</param>
/// <returns>查询结果。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持此成员。</exception>
public TResponse SendQuery<TResponse>(GFramework.Cqrs.Abstractions.Cqrs.Query.IQuery<TResponse> query)
{
throw new NotSupportedException();
}
/// <summary>
/// 测试桩:异步发布 CQRS 通知。
/// </summary>
/// <typeparam name="TNotification">通知类型。</typeparam>
/// <param name="notification">要发布的通知。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>通知发布任务。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持此成员。</exception>
public ValueTask PublishAsync<TNotification>(
TNotification notification,
CancellationToken cancellationToken = default)
where TNotification : INotification
{
throw new NotSupportedException();
}
/// <summary>
/// 测试桩:创建 CQRS 流式请求响应序列。
/// </summary>
/// <typeparam name="TResponse">流式响应元素类型。</typeparam>
/// <param name="request">流式请求。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>异步响应流。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持此成员。</exception>
public IAsyncEnumerable<TResponse> CreateStream<TResponse>(
IStreamRequest<TResponse> request,
CancellationToken cancellationToken = default)
{
throw new NotSupportedException();
}
/// <summary>
/// 测试桩:异步发送无返回值 CQRS 命令。
/// </summary>
/// <typeparam name="TCommand">命令类型。</typeparam>
/// <param name="command">要发送的命令。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>命令发送任务。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持此成员。</exception>
public ValueTask SendAsync<TCommand>(TCommand command, CancellationToken cancellationToken = default)
where TCommand : IRequest<Unit>
{
throw new NotSupportedException();
}
/// <summary>
/// 测试桩:异步发送带返回值的 CQRS 请求。
/// </summary>
/// <typeparam name="TResponse">响应类型。</typeparam>
/// <param name="command">要发送的请求。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>请求响应任务。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持此成员。</exception>
public ValueTask<TResponse> SendAsync<TResponse>(
IRequest<TResponse> command,
CancellationToken cancellationToken = default)
{
throw new NotSupportedException();
}
/// <summary>
/// 发送旧版命令。
/// </summary>
/// <param name="command">命令对象。</param>
/// <exception cref="NotSupportedException">该测试桩不支持旧版命令执行入口。</exception>
public void SendCommand(ICommand command)
{
throw new NotSupportedException();
}
/// <summary>
/// 发送旧版带返回值命令。
/// </summary>
/// <typeparam name="TResult">返回值类型。</typeparam>
/// <param name="command">命令对象。</param>
/// <returns>此方法始终抛出异常,不返回结果。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持旧版命令执行入口。</exception>
public TResult SendCommand<TResult>(ICommand<TResult> command)
{
throw new NotSupportedException();
}
/// <summary>
/// 异步发送旧版命令。
/// </summary>
/// <param name="command">命令对象。</param>
/// <returns>已失败的任务。</returns>
public Task SendCommandAsync(IAsyncCommand command)
{
return Task.FromException(new NotSupportedException());
}
/// <summary>
/// 异步发送旧版带返回值命令。
/// </summary>
/// <typeparam name="TResult">返回值类型。</typeparam>
/// <param name="command">命令对象。</param>
/// <returns>已失败的任务。</returns>
public Task<TResult> SendCommandAsync<TResult>(IAsyncCommand<TResult> command)
{
return Task.FromException<TResult>(new NotSupportedException());
}
/// <summary>
/// 发送旧版查询请求。
/// </summary>
/// <typeparam name="TResult">查询结果类型。</typeparam>
/// <param name="query">查询对象。</param>
/// <returns>此方法始终抛出异常,不返回结果。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持旧版查询执行入口。</exception>
public TResult SendQuery<TResult>(IQuery<TResult> query)
{
throw new NotSupportedException();
}
/// <summary>
/// 异步发送旧版查询请求。
/// </summary>
/// <typeparam name="TResult">查询结果类型。</typeparam>
/// <param name="query">异步查询对象。</param>
/// <returns>已失败的任务。</returns>
public Task<TResult> SendQueryAsync<TResult>(IAsyncQuery<TResult> query)
{
return Task.FromException<TResult>(new NotSupportedException());
}
/// <summary>
/// 获取当前环境对象。
/// </summary>
/// <returns>默认测试环境对象。</returns>
public IEnvironment GetEnvironment()
{
return Environment;
}
}

View File

@ -1,426 +1,16 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using GFramework.Core.Abstractions.Architectures;
using GFramework.Core.Abstractions.Command;
using GFramework.Core.Abstractions.Environment;
using GFramework.Core.Abstractions.Events;
using GFramework.Core.Abstractions.Model;
using GFramework.Core.Abstractions.Query;
using GFramework.Core.Abstractions.Systems;
using GFramework.Core.Abstractions.Utility;
using GFramework.Core.Environment;
using GFramework.Core.Events;
using GFramework.Core.Ioc;
using GFramework.Cqrs;
using GFramework.Cqrs.Abstractions.Cqrs;
using ICommand = GFramework.Core.Abstractions.Command.ICommand;
namespace GFramework.Core.Tests.Architectures;
/// <summary>
/// 为 <see cref="ArchitectureServicesTests" /> 提供最小实现的架构上下文测试桩。
/// </summary>
/// <remarks>
/// 该类型仅用于验证 <see cref="ArchitectureServices" /> 的上下文传递行为,因此仅保留当前测试切片需要的容器、
/// 环境与接口实现。所有不在本测试范围内的 CQRS 调用均明确抛出 <see cref="NotSupportedException" />
/// 以避免误把测试桩当作真实运行时上下文使用。
/// 共享的容器解析、事件总线协作与 legacy CQRS 失败契约由 <see cref="TestArchitectureContextBase" /> 提供,
/// 当前类型只补充 <see cref="ArchitectureServicesTests" /> 需要的上下文实例标识。
/// </remarks>
public class TestArchitectureContextV3 : IArchitectureContext
public class TestArchitectureContextV3 : TestArchitectureContextBase
{
private readonly MicrosoftDiContainer _container = new();
private readonly DefaultEnvironment _environment = new();
private readonly EventBus _eventBus = new();
/// <summary>
/// 获取或初始化用于区分测试上下文实例的标识。
/// </summary>
public int Id { get; init; }
/// <summary>
/// 获取指定类型的服务实例。
/// </summary>
/// <typeparam name="TService">服务类型。</typeparam>
/// <returns>已注册的服务实例。</returns>
/// <exception cref="InvalidOperationException">未注册或存在多个同类型实例时抛出。</exception>
public TService GetService<TService>() where TService : class
{
return _container.GetRequired<TService>();
}
/// <summary>
/// 获取指定类型的所有服务实例。
/// </summary>
/// <typeparam name="TService">服务类型。</typeparam>
/// <returns>所有已注册的服务实例。</returns>
public IReadOnlyList<TService> GetServices<TService>() where TService : class
{
return _container.GetAll<TService>();
}
/// <summary>
/// 获取指定类型的模型实例。
/// </summary>
/// <typeparam name="TModel">模型类型。</typeparam>
/// <returns>已注册的模型实例。</returns>
/// <exception cref="InvalidOperationException">未注册或存在多个同类型实例时抛出。</exception>
public TModel GetModel<TModel>() where TModel : class, IModel
{
return _container.GetRequired<TModel>();
}
/// <summary>
/// 获取指定类型的所有模型实例。
/// </summary>
/// <typeparam name="TModel">模型类型。</typeparam>
/// <returns>所有已注册的模型实例。</returns>
public IReadOnlyList<TModel> GetModels<TModel>() where TModel : class, IModel
{
return _container.GetAll<TModel>();
}
/// <summary>
/// 获取指定类型的系统实例。
/// </summary>
/// <typeparam name="TSystem">系统类型。</typeparam>
/// <returns>已注册的系统实例。</returns>
/// <exception cref="InvalidOperationException">未注册或存在多个同类型实例时抛出。</exception>
public TSystem GetSystem<TSystem>() where TSystem : class, ISystem
{
return _container.GetRequired<TSystem>();
}
/// <summary>
/// 获取指定类型的所有系统实例。
/// </summary>
/// <typeparam name="TSystem">系统类型。</typeparam>
/// <returns>所有已注册的系统实例。</returns>
public IReadOnlyList<TSystem> GetSystems<TSystem>() where TSystem : class, ISystem
{
return _container.GetAll<TSystem>();
}
/// <summary>
/// 获取指定类型的工具实例。
/// </summary>
/// <typeparam name="TUtility">工具类型。</typeparam>
/// <returns>已注册的工具实例。</returns>
/// <exception cref="InvalidOperationException">未注册或存在多个同类型实例时抛出。</exception>
public TUtility GetUtility<TUtility>() where TUtility : class, IUtility
{
return _container.GetRequired<TUtility>();
}
/// <summary>
/// 获取指定类型的所有工具实例。
/// </summary>
/// <typeparam name="TUtility">工具类型。</typeparam>
/// <returns>所有已注册的工具实例。</returns>
public IReadOnlyList<TUtility> GetUtilities<TUtility>() where TUtility : class, IUtility
{
return _container.GetAll<TUtility>();
}
/// <summary>
/// 获取指定类型的所有服务实例,并按优先级排序。
/// </summary>
/// <typeparam name="TService">服务类型。</typeparam>
/// <returns>按优先级排序后的服务实例。</returns>
public IReadOnlyList<TService> GetServicesByPriority<TService>() where TService : class
{
return _container.GetAllByPriority<TService>();
}
/// <summary>
/// 获取指定类型的所有系统实例,并按优先级排序。
/// </summary>
/// <typeparam name="TSystem">系统类型。</typeparam>
/// <returns>按优先级排序后的系统实例。</returns>
public IReadOnlyList<TSystem> GetSystemsByPriority<TSystem>() where TSystem : class, ISystem
{
return _container.GetAllByPriority<TSystem>();
}
/// <summary>
/// 获取指定类型的所有模型实例,并按优先级排序。
/// </summary>
/// <typeparam name="TModel">模型类型。</typeparam>
/// <returns>按优先级排序后的模型实例。</returns>
public IReadOnlyList<TModel> GetModelsByPriority<TModel>() where TModel : class, IModel
{
return _container.GetAllByPriority<TModel>();
}
/// <summary>
/// 获取指定类型的所有工具实例,并按优先级排序。
/// </summary>
/// <typeparam name="TUtility">工具类型。</typeparam>
/// <returns>按优先级排序后的工具实例。</returns>
public IReadOnlyList<TUtility> GetUtilitiesByPriority<TUtility>() where TUtility : class, IUtility
{
return _container.GetAllByPriority<TUtility>();
}
/// <summary>
/// 发送无参数事件。
/// </summary>
/// <typeparam name="TEvent">事件类型。</typeparam>
public void SendEvent<TEvent>() where TEvent : new()
{
_eventBus.Send<TEvent>();
}
/// <summary>
/// 发送带参数事件。
/// </summary>
/// <typeparam name="TEvent">事件类型。</typeparam>
/// <param name="e">事件实例。</param>
/// <exception cref="ArgumentNullException"><paramref name="e" /> 为 <see langword="null" />。</exception>
public void SendEvent<TEvent>(TEvent e) where TEvent : class
{
ArgumentNullException.ThrowIfNull(e);
_eventBus.Send(e);
}
/// <summary>
/// 注册事件处理器。
/// </summary>
/// <typeparam name="TEvent">事件类型。</typeparam>
/// <param name="handler">事件处理回调。</param>
/// <returns>用于注销回调的句柄。</returns>
/// <exception cref="ArgumentNullException"><paramref name="handler" /> 为 <see langword="null" />。</exception>
public IUnRegister RegisterEvent<TEvent>(Action<TEvent> handler)
{
ArgumentNullException.ThrowIfNull(handler);
return _eventBus.Register(handler);
}
/// <summary>
/// 取消事件处理器注册。
/// </summary>
/// <typeparam name="TEvent">事件类型。</typeparam>
/// <param name="onEvent">要取消的事件回调。</param>
/// <exception cref="ArgumentNullException"><paramref name="onEvent" /> 为 <see langword="null" />。</exception>
public void UnRegisterEvent<TEvent>(Action<TEvent> onEvent)
{
ArgumentNullException.ThrowIfNull(onEvent);
_eventBus.UnRegister(onEvent);
}
/// <summary>
/// 异步发送新版 CQRS 请求。
/// </summary>
/// <typeparam name="TResponse">响应类型。</typeparam>
/// <param name="request">要发送的请求。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>请求响应任务。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持此成员。</exception>
public ValueTask<TResponse> SendRequestAsync<TResponse>(
IRequest<TResponse> request,
CancellationToken cancellationToken = default)
{
throw new NotSupportedException();
}
/// <summary>
/// 同步发送新版 CQRS 请求。
/// </summary>
/// <typeparam name="TResponse">响应类型。</typeparam>
/// <param name="request">要发送的请求。</param>
/// <returns>请求响应。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持此成员。</exception>
public TResponse SendRequest<TResponse>(IRequest<TResponse> request)
{
throw new NotSupportedException();
}
/// <summary>
/// 异步发送新版 CQRS 命令并返回响应。
/// </summary>
/// <typeparam name="TResponse">命令响应类型。</typeparam>
/// <param name="command">要发送的命令。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>命令响应任务。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持此成员。</exception>
public ValueTask<TResponse> SendCommandAsync<TResponse>(
GFramework.Cqrs.Abstractions.Cqrs.Command.ICommand<TResponse> command,
CancellationToken cancellationToken = default)
{
throw new NotSupportedException();
}
/// <summary>
/// 同步发送新版 CQRS 命令并返回响应。
/// </summary>
/// <typeparam name="TResponse">命令响应类型。</typeparam>
/// <param name="command">要发送的命令。</param>
/// <returns>命令响应。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持此成员。</exception>
public TResponse SendCommand<TResponse>(GFramework.Cqrs.Abstractions.Cqrs.Command.ICommand<TResponse> command)
{
throw new NotSupportedException();
}
/// <summary>
/// 异步发送新版 CQRS 查询并返回结果。
/// </summary>
/// <typeparam name="TResponse">查询结果类型。</typeparam>
/// <param name="query">要发送的查询。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>查询结果任务。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持此成员。</exception>
public ValueTask<TResponse> SendQueryAsync<TResponse>(
GFramework.Cqrs.Abstractions.Cqrs.Query.IQuery<TResponse> query,
CancellationToken cancellationToken = default)
{
throw new NotSupportedException();
}
/// <summary>
/// 同步发送新版 CQRS 查询并返回结果。
/// </summary>
/// <typeparam name="TResponse">查询结果类型。</typeparam>
/// <param name="query">要发送的查询。</param>
/// <returns>查询结果。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持此成员。</exception>
public TResponse SendQuery<TResponse>(GFramework.Cqrs.Abstractions.Cqrs.Query.IQuery<TResponse> query)
{
throw new NotSupportedException();
}
/// <summary>
/// 发布通知消息。
/// </summary>
/// <typeparam name="TNotification">通知类型。</typeparam>
/// <param name="notification">通知实例。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>通知发布任务。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持此成员。</exception>
public ValueTask PublishAsync<TNotification>(
TNotification notification,
CancellationToken cancellationToken = default)
where TNotification : INotification
{
throw new NotSupportedException();
}
/// <summary>
/// 创建流式请求结果。
/// </summary>
/// <typeparam name="TResponse">流元素类型。</typeparam>
/// <param name="request">流式请求。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>流式响应序列。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持此成员。</exception>
public IAsyncEnumerable<TResponse> CreateStream<TResponse>(
IStreamRequest<TResponse> request,
CancellationToken cancellationToken = default)
{
throw new NotSupportedException();
}
/// <summary>
/// 异步发送无返回值请求命令。
/// </summary>
/// <typeparam name="TCommand">命令类型。</typeparam>
/// <param name="command">要发送的命令。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>命令发送任务。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持此成员。</exception>
public ValueTask SendAsync<TCommand>(TCommand command, CancellationToken cancellationToken = default)
where TCommand : IRequest<Unit>
{
throw new NotSupportedException();
}
/// <summary>
/// 异步发送带返回值请求。
/// </summary>
/// <typeparam name="TResponse">响应类型。</typeparam>
/// <param name="command">要发送的请求。</param>
/// <param name="cancellationToken">取消令牌。</param>
/// <returns>请求响应任务。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持此成员。</exception>
public ValueTask<TResponse> SendAsync<TResponse>(
IRequest<TResponse> command,
CancellationToken cancellationToken = default)
{
throw new NotSupportedException();
}
/// <summary>
/// 发送旧版无返回值命令。
/// </summary>
/// <param name="command">要发送的命令。</param>
/// <exception cref="NotSupportedException">该测试桩不支持旧版命令执行入口。</exception>
public void SendCommand(ICommand command)
{
throw new NotSupportedException();
}
/// <summary>
/// 发送旧版带返回值命令。
/// </summary>
/// <typeparam name="TResult">命令响应类型。</typeparam>
/// <param name="command">要发送的命令。</param>
/// <returns>此方法始终抛出异常,不返回结果。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持旧版命令执行入口。</exception>
public TResult SendCommand<TResult>(GFramework.Core.Abstractions.Command.ICommand<TResult> command)
{
throw new NotSupportedException();
}
/// <summary>
/// 异步发送旧版无返回值命令。
/// </summary>
/// <param name="command">要发送的命令。</param>
/// <returns>已失败的任务。</returns>
public Task SendCommandAsync(IAsyncCommand command)
{
return Task.FromException(new NotSupportedException());
}
/// <summary>
/// 异步发送旧版带返回值命令。
/// </summary>
/// <typeparam name="TResult">命令响应类型。</typeparam>
/// <param name="command">要发送的命令。</param>
/// <returns>已失败的任务。</returns>
public Task<TResult> SendCommandAsync<TResult>(IAsyncCommand<TResult> command)
{
return Task.FromException<TResult>(new NotSupportedException());
}
/// <summary>
/// 发送旧版查询请求。
/// </summary>
/// <typeparam name="TResult">查询结果类型。</typeparam>
/// <param name="query">要发送的查询。</param>
/// <returns>此方法始终抛出异常,不返回结果。</returns>
/// <exception cref="NotSupportedException">该测试桩不支持旧版查询执行入口。</exception>
public TResult SendQuery<TResult>(GFramework.Core.Abstractions.Query.IQuery<TResult> query)
{
throw new NotSupportedException();
}
/// <summary>
/// 异步发送旧版查询请求。
/// </summary>
/// <typeparam name="TResult">查询结果类型。</typeparam>
/// <param name="query">要发送的查询。</param>
/// <returns>已失败的任务。</returns>
public Task<TResult> SendQueryAsync<TResult>(IAsyncQuery<TResult> query)
{
return Task.FromException<TResult>(new NotSupportedException());
}
/// <summary>
/// 获取当前测试上下文绑定的环境实例。
/// </summary>
/// <returns>默认测试环境实例。</returns>
public IEnvironment GetEnvironment()
{
return _environment;
}
}

View File

@ -6,13 +6,12 @@
## 当前恢复点
- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-090`
- 当前阶段:`Phase 90`
- 恢复点编号:`ANALYZER-WARNING-REDUCTION-RP-091`
- 当前阶段:`Phase 91`
- 当前焦点:
- `2026-04-28` 再次执行 `$gframework-pr-review`,确认 `PR #300` 最新 head 仍显示 `6` 条 CodeRabbit open threads但本地复核后只有事件 API 回归覆盖仍然成立
- 已在 `TestArchitectureContextBehaviorTests.cs` 补齐 `UnRegisterEvent` 行为与 `SendEvent` / `RegisterEvent` / `UnRegisterEvent` 的空参数契约测试
- 已整理 `TestResourceLoader.cs` 的命名空间缩进,收口本轮顺手处理的局部格式噪音
- `dotnet format --verify-no-changes` 当前仍会暴露 `GFramework.Core.Tests` 项目里跨多个无关文件的既有 `FINALNEWLINE``CHARSET``WHITESPACE` 基线,本轮不扩展到整项目格式波次
- `2026-04-28` 继续收口 `PR #300` 的剩余 nitpick已把 `TestArchitectureContext` / `TestArchitectureContextV3` 的重复 `IArchitectureContext` 测试实现抽到共享基类 `TestArchitectureContextBase`
- 已将 “本地验证后仍然成立的 nitpick 不得默认降级为可选项” 写入 `.agents/skills/gframework-pr-review/SKILL.md`
- `dotnet format --verify-no-changes``GFramework.Core.Tests` 既有 `FINALNEWLINE``CHARSET``WHITESPACE` 基线仍保持独立,不与本轮共享基类重构混提
## 当前活跃事实
@ -20,12 +19,10 @@
- 当前直接验证结果:
- `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release`
- 最新结果:成功;`0 Warning(s)``0 Error(s)`
- `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --no-build --filter "FullyQualifiedName~TestArchitectureContextBehaviorTests"`
- 最新结果:成功;`9` 通过、`0` 失败
- `dotnet format GFramework.Core.Tests/GFramework.Core.Tests.csproj --verify-no-changes --no-restore`
- 最新结果:失败;暴露 `GFramework.Core.Tests` 项目中跨多个未触碰文件的既有 `FINALNEWLINE``CHARSET``WHITESPACE` 诊断,本轮新增写集未引入 `git diff --check` 异常
- `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --no-build --filter "FullyQualifiedName~ArchitectureServicesTests|FullyQualifiedName~ContextAwareServiceExtensionsTests|FullyQualifiedName~TestArchitectureContextBehaviorTests|FullyQualifiedName~RegistryInitializationHookBaseTests|FullyQualifiedName~ArchitectureContextTests"`
- 最新结果:成功;`67` 通过、`0` 失败
- 当前批次摘要:
- 当前工作树包含 `4` 个已修改文件,分别位于 `GFramework.Core.Tests` 与 `ai-plan/public/analyzer-warning-reduction`
- 当前工作树包含 `6` 个已修改文件与 `1` 个新增文件,分别位于 `GFramework.Core.Tests``.agents/skills/gframework-pr-review/``ai-plan/public/analyzer-warning-reduction`
- 本轮没有触碰 `Mediator/*``YamlConfigSchemaValidator*``GFramework.Core.Tests` 的整项目格式基线波次
## 当前风险
@ -60,6 +57,6 @@
## 下一步建议
1. 提交本轮 `PR #300` review follow-up `ai-plan` 同步。
2. 若需要继续收口 PR 线程,可单独评估是否接受 `TestArchitectureContext` / `TestArchitectureContextV3` 的共享 helper nitpick
1. 提交本轮 `PR #300` nitpick follow-up、技能规则更新`ai-plan` 同步。
2. 推送后重新执行 `$gframework-pr-review`,确认该 nitpick thread 是否随最新 head 自动收口
3. 若要清理 `dotnet format` 基线,另开 `GFramework.Core.Tests` 格式治理切片,不与当前 PR review 修复混提。

View File

@ -1,23 +1,21 @@
# Analyzer Warning Reduction 追踪
## 2026-04-28 — RP-090
## 2026-04-28 — RP-091
### 阶段:复核 `PR #300` 最新 review 真值并补齐事件 API 回归覆盖
### 阶段:收口 `PR #300` 的共享测试基础设施 nitpick并升级 PR-review triage 规则
- 触发背景:
- 用户再次执行 `$gframework-pr-review`
- `fetch_current_pr_review.py --json-output /tmp/gframework-current-pr-review.json` 返回 `PR #300`latest head 仍显示 `6` 条 CodeRabbit open threads本地复核后`Task.CompletedTask` 强转、`RegisterLifecycleHook` 语义、`TestResourceLoader` 文档与 `PartialGeneratedNotificationHandlerRegistry` XML 契约都已在当前 head 上成立,唯一仍未锁住的是事件 API 回归覆盖
- 用户追问 `TestArchitectureContext` / `TestArchitectureContextV3` 的共享基础设施 nitpick 是否已经处理完成
- 同时要求把“本地验证后仍然成立的 nitpick 不能默认降级为可选项”写入 `AGENTS.md``$gframework-pr-review`
- 主线程实施:
- `TestArchitectureContext``TestArchitectureContextV3` 新增共享测试数据源,补齐 `SendEvent` / `RegisterEvent` / `UnRegisterEvent` 的空参数异常契约
- 新增 `UnRegisterEvent_Should_Stop_Dispatch` 回归测试,防止后续把注销路径退化成 `no-op`
- 整理 `TestResourceLoader.cs` 的命名空间缩进,避免当前修改继续叠加局部格式噪音
- 新增 `TestArchitectureContextBase`,把容器解析、共享 `EventBus` 行为,以及 legacy / CQRS 失败契约统一收敛到一处
- `TestArchitectureContext``TestArchitectureContextV3` 收窄为薄包装类型,只保留各自的命名入口与 `Id` 差异
- 更新 `.agents/skills/gframework-pr-review/SKILL.md`明确要求latest-head `Nitpick comment` 一旦本地验证仍成立且指向真实漂移/回归风险,就必须作为 actionable review input 处理,而不是默认视作可选
- 验证里程碑:
- `dotnet build GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release`
- 结果:成功;`0 Warning(s)``0 Error(s)`
- `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --no-build --filter "FullyQualifiedName~TestArchitectureContextBehaviorTests"`
- 结果:成功;`9` 通过、`0` 失败
- `dotnet format GFramework.Core.Tests/GFramework.Core.Tests.csproj --verify-no-changes --no-restore`
- 结果:失败;输出落在 `ObjectExtensionsTests.cs`、多处 `FINALNEWLINE` 与若干 `CHARSET` 基线文件,均不属于本轮写集
- `dotnet test GFramework.Core.Tests/GFramework.Core.Tests.csproj -c Release --no-build --filter "FullyQualifiedName~ArchitectureServicesTests|FullyQualifiedName~ContextAwareServiceExtensionsTests|FullyQualifiedName~TestArchitectureContextBehaviorTests|FullyQualifiedName~RegistryInitializationHookBaseTests|FullyQualifiedName~ArchitectureContextTests"`
- 结果:成功;`67` 通过、`0` 失败
- `git diff --check`
- 结果:成功;无新增 whitespace / conflict-marker 问题
@ -30,8 +28,8 @@
## 下一步
1. 提交本轮 `PR #300` follow-up `ai-plan` 同步。
2. 若继续收口 PR 线程,单独评估是否接受 `TestArchitectureContext` / `TestArchitectureContextV3` 的共享 helper nitpick
1. 提交本轮共享基类重构、技能规则更新`ai-plan` 同步。
2. 推送后重新执行 `$gframework-pr-review`,确认剩余 PR 线程是否已经下降
## 历史归档指针