// Copyright (c) 2025-2026 GeWuYou // SPDX-License-Identifier: Apache-2.0 using GFramework.Core.Abstractions.Command; using GFramework.Core.Abstractions.Rule; using GFramework.Core.Cqrs; using GFramework.Core.Rule; using GFramework.Core.Tests.Architectures; namespace GFramework.Core.Tests.Cqrs; /// /// 验证 legacy 异步无返回值命令 bridge handler 的取消语义。 /// [TestFixture] public class LegacyAsyncCommandDispatchRequestHandlerTests { /// /// 验证当取消令牌在执行前已触发时,handler 不会启动底层 legacy 命令。 /// [Test] public void Handle_Should_Throw_Without_Executing_Command_When_Cancellation_Is_Already_Requested() { var handler = new LegacyAsyncCommandDispatchRequestHandler(); var command = new ProbeAsyncCommand(Task.CompletedTask); using var cancellationTokenSource = new CancellationTokenSource(); cancellationTokenSource.Cancel(); Assert.ThrowsAsync( async () => await handler.Handle( new LegacyAsyncCommandDispatchRequest(command), cancellationTokenSource.Token) .AsTask() .ConfigureAwait(false)); Assert.That(command.ExecutionCount, Is.Zero); } /// /// 验证当底层 legacy 命令正在运行时,handler 会通过 WaitAsync 及时向调用方暴露取消。 /// [Test] public async Task Handle_Should_Observe_Cancellation_While_Command_Is_Running() { var completionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); var handler = new LegacyAsyncCommandDispatchRequestHandler(); var command = new ProbeAsyncCommand(completionSource.Task); using var cancellationTokenSource = new CancellationTokenSource(); ((IContextAware)handler).SetContext(new TestArchitectureContextBaseStub()); var handleTask = handler.Handle( new LegacyAsyncCommandDispatchRequest(command), cancellationTokenSource.Token) .AsTask(); cancellationTokenSource.Cancel(); Assert.That( async () => await handleTask.ConfigureAwait(false), Throws.InstanceOf()); Assert.That(command.ExecutionCount, Is.EqualTo(1)); } /// /// 为 handler 取消测试提供可控完成时机的异步命令替身。 /// private sealed class ProbeAsyncCommand(Task executionTask) : ContextAwareBase, IAsyncCommand { /// /// 获取底层命令逻辑的触发次数。 /// public int ExecutionCount { get; private set; } /// public Task ExecuteAsync() { ExecutionCount++; return executionTask; } } /// /// 为 handler 取消测试提供最小架构上下文替身。 /// private sealed class TestArchitectureContextBaseStub : TestArchitectureContextBase { } }