// Copyright (c) 2025-2026 GeWuYou
// SPDX-License-Identifier: Apache-2.0
using GFramework.Core.Abstractions.Architectures;
using GFramework.Core.Abstractions.Ioc;
using GFramework.Core.Abstractions.Logging;
using GFramework.Core.Architectures;
using GFramework.Core.Ioc;
using GFramework.Core.Logging;
using GFramework.Cqrs.Abstractions.Cqrs;
using GFramework.Cqrs.Cqrs;
using GFramework.Cqrs.Notification;
using GFramework.Cqrs.Tests.Logging;
namespace GFramework.Cqrs.Tests.Cqrs;
///
/// 验证默认 CQRS runtime 的通知发布策略接缝。
///
[TestFixture]
internal sealed class CqrsNotificationPublisherTests
{
///
/// 验证当调用方显式提供自定义通知发布器时,dispatcher 会按该发布器定义的顺序执行处理器。
///
[Test]
public async Task PublishAsync_Should_Use_Custom_NotificationPublisher_When_Runtime_Is_Created_With_It()
{
var invocationOrder = new List();
var handlers = new object[]
{
new RecordingNotificationHandler("first", invocationOrder),
new RecordingNotificationHandler("second", invocationOrder)
};
var runtime = CreateRuntime(
container =>
{
container
.Setup(currentContainer => currentContainer.GetAll(typeof(INotificationHandler)))
.Returns(handlers);
},
new ReverseOrderNotificationPublisher());
await runtime.PublishAsync(new FakeCqrsContext(), new PublisherNotification()).ConfigureAwait(false);
Assert.That(invocationOrder, Is.EqualTo(["second", "first"]));
}
///
/// 验证当容器在 runtime 创建前已显式注册自定义通知发布器时,
/// `RegisterInfrastructure` 这条默认接线会复用该策略。
///
[Test]
public async Task RegisterInfrastructure_Should_Use_PreRegistered_NotificationPublisher()
{
LoggerFactoryResolver.Provider = new ConsoleLoggerFactoryProvider();
var container = new MicrosoftDiContainer();
var publisher = new TrackingNotificationPublisher();
container.Register(publisher);
container.Register>(new RecordingNotificationHandler("only", []));
CqrsTestRuntime.RegisterInfrastructure(container);
container.Freeze();
var context = new ArchitectureContext(container);
await context.PublishAsync(new PublisherNotification()).ConfigureAwait(false);
Assert.That(publisher.WasCalled, Is.True);
}
///
/// 验证自定义通知发布器通过发布上下文回调执行处理器时,dispatcher 仍会在调用前注入当前架构上下文。
///
[Test]
public async Task PublishAsync_Should_Prepare_Context_Before_Custom_Publisher_Invokes_Handler()
{
var handler = new ContextAwarePublisherTestHandler();
var architectureContext = new Mock(MockBehavior.Strict);
var runtime = CreateRuntime(
container =>
{
container
.Setup(currentContainer => currentContainer.GetAll(typeof(INotificationHandler)))
.Returns([handler]);
},
new PassthroughNotificationPublisher());
await runtime.PublishAsync(architectureContext.Object, new PublisherNotification()).ConfigureAwait(false);
Assert.That(handler.ObservedContext, Is.SameAs(architectureContext.Object));
}
///
/// 验证默认通知发布器在零处理器场景下会保持静默完成。
///
[Test]
public void PublishAsync_Should_Complete_When_No_Handlers_Are_Registered()
{
var runtime = CreateRuntime(
container =>
{
container
.Setup(currentContainer => currentContainer.GetAll(typeof(INotificationHandler)))
.Returns(Array.Empty