// Copyright (c) 2025-2026 GeWuYou
// SPDX-License-Identifier: Apache-2.0
using GFramework.Core.Abstractions.Architectures;
using GFramework.Core.Abstractions.Rule;
using GFramework.Cqrs.Abstractions.Cqrs;
using GFramework.Cqrs.Abstractions.Cqrs.Command;
using GFramework.Cqrs.Cqrs.Command;
namespace GFramework.Cqrs.Tests.Cqrs;
///
/// 验证 CQRS handler 基类在脱离 dispatcher 使用时会显式失败,并在注入上下文后保持可观察行为。
///
[TestFixture]
internal sealed class AbstractCqrsHandlerContextTests
{
///
/// 验证新的轻量 handler 基类不会再偷偷回退到全局 GameContext。
///
[Test]
public void GetContext_Should_Throw_When_Handler_Has_Not_Been_Initialized_By_Runtime()
{
var handler = new TestCommandHandler();
var exception = Assert.Throws(() => ((IContextAware)handler).GetContext());
Assert.That(
exception!.Message,
Does.Contain("has not been initialized").IgnoreCase);
}
///
/// 验证 runtime 注入上下文后,派生 handler 可以继续访问 Context 并收到 OnContextReady 回调。
///
[Test]
public async Task Handle_Should_Observe_Injected_Context_And_OnContextReady_Callback()
{
var handler = new TestCommandHandler();
var context = new Mock(MockBehavior.Strict).Object;
((IContextAware)handler).SetContext(context);
await handler.Handle(new TestCommand(), CancellationToken.None);
Assert.Multiple(() =>
{
Assert.That(handler.OnContextReadyCallCount, Is.EqualTo(1));
Assert.That(handler.LastObservedContext, Is.SameAs(context));
});
}
///
/// 用于验证上下文注入行为的最小 CQRS 命令。
///
private sealed record TestCommand : ICommand;
///
/// 暴露基类上下文访问与初始化回调的测试处理器。
///
private sealed class TestCommandHandler : AbstractCommandHandler
{
public int OnContextReadyCallCount { get; private set; }
public IArchitectureContext? LastObservedContext { get; private set; }
protected override void OnContextReady()
{
OnContextReadyCallCount++;
}
public override ValueTask Handle(TestCommand command, CancellationToken cancellationToken)
{
LastObservedContext = Context;
return ValueTask.FromResult(Unit.Value);
}
}
}