Skip to content
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using GFramework.Cqrs.Abstractions.Cqrs;

namespace GFramework.Core.Tests.Architectures;

/// <summary>
/// 用于验证额外程序集接入是否成功的测试通知。
/// </summary>
public sealed record AdditionalAssemblyNotification : INotification;
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using GFramework.Core.Abstractions.Logging;
using GFramework.Cqrs;
using GFramework.Cqrs.Abstractions.Cqrs;

namespace GFramework.Core.Tests.Architectures;

/// <summary>
/// 模拟由 source-generator 为扩展程序集生成的 CQRS handler registry。
/// </summary>
internal sealed class AdditionalAssemblyNotificationHandlerRegistry : ICqrsHandlerRegistry
{
/// <summary>
/// 将扩展程序集中的通知处理器映射写入服务集合。
/// </summary>
/// <param name="services">目标服务集合。</param>
/// <param name="logger">日志记录器。</param>
/// <exception cref="ArgumentNullException">
/// 当 <paramref name="services" /> 或 <paramref name="logger" /> 为 <see langword="null" /> 时抛出。
/// </exception>
public void Register(IServiceCollection services, ILogger logger)
{
ArgumentNullException.ThrowIfNull(services);
ArgumentNullException.ThrowIfNull(logger);

services.AddTransient<INotificationHandler<AdditionalAssemblyNotification>>(_ => CreateHandler());
logger.Debug(
$"Registered CQRS handler proxy for {typeof(INotificationHandler<AdditionalAssemblyNotification>).FullName}.");
}

/// <summary>
/// 创建一个仅供显式程序集注册路径使用的动态通知处理器。
/// </summary>
/// <returns>用于记录通知触发次数的测试替身处理器。</returns>
private static INotificationHandler<AdditionalAssemblyNotification> CreateHandler()
{
var handler = new Mock<INotificationHandler<AdditionalAssemblyNotification>>();
handler
.Setup(target => target.Handle(It.IsAny<AdditionalAssemblyNotification>(), It.IsAny<CancellationToken>()))
.Returns(() =>
{
AdditionalAssemblyNotificationHandlerState.RecordInvocation();
return ValueTask.CompletedTask;
});
return handler.Object;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
namespace GFramework.Core.Tests.Architectures;

/// <summary>
/// 记录模拟扩展程序集通知处理器的执行次数。
/// </summary>
public static class AdditionalAssemblyNotificationHandlerState
{
private static int _invocationCount;

/// <summary>
/// 获取当前测试进程中该处理器的执行次数。
/// </summary>
/// <remarks>
/// 该计数器通过原子读写维护,以支持 NUnit 并行执行环境中的并发访问。
/// </remarks>
public static int InvocationCount => Volatile.Read(ref _invocationCount);

/// <summary>
/// 记录一次通知处理,供测试断言显式程序集接入后的运行时行为。
/// </summary>
public static void RecordInvocation()
{
Interlocked.Increment(ref _invocationCount);
}

/// <summary>
/// 清理共享计数器,避免测试间相互污染。
/// </summary>
public static void Reset()
{
Interlocked.Exchange(ref _invocationCount, 0);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -121,88 +121,3 @@ private static SyncTestArchitecture CreateArchitecture(Action<TestArchitectureBa
return architecture;
}
}

/// <summary>
/// 用于验证额外程序集接入是否成功的测试通知。
/// </summary>
public sealed record AdditionalAssemblyNotification : INotification;

/// <summary>
/// 记录模拟扩展程序集通知处理器的执行次数。
/// </summary>
public static class AdditionalAssemblyNotificationHandlerState
{
private static int _invocationCount;

/// <summary>
/// 获取当前测试进程中该处理器的执行次数。
/// </summary>
/// <remarks>
/// 该计数器通过原子读写维护,以支持 NUnit 并行执行环境中的并发访问。
/// </remarks>
public static int InvocationCount => Volatile.Read(ref _invocationCount);

/// <summary>
/// 记录一次通知处理,供测试断言显式程序集接入后的运行时行为。
/// </summary>
public static void RecordInvocation()
{
Interlocked.Increment(ref _invocationCount);
}

/// <summary>
/// 清理共享计数器,避免测试间相互污染。
/// </summary>
public static void Reset()
{
Interlocked.Exchange(ref _invocationCount, 0);
}
}

/// <summary>
/// 模拟由 source-generator 为扩展程序集生成的 CQRS handler registry。
/// </summary>
internal sealed class AdditionalAssemblyNotificationHandlerRegistry : ICqrsHandlerRegistry
{
/// <summary>
/// 将扩展程序集中的通知处理器映射写入服务集合。
/// </summary>
/// <param name="services">目标服务集合。</param>
/// <param name="logger">日志记录器。</param>
/// <exception cref="ArgumentNullException">
/// 当 <paramref name="services" /> 或 <paramref name="logger" /> 为 <see langword="null" /> 时抛出。
/// </exception>
public void Register(IServiceCollection services, ILogger logger)
{
if (services is null)
{
throw new ArgumentNullException(nameof(services));
}

if (logger is null)
{
throw new ArgumentNullException(nameof(logger));
}

services.AddTransient<INotificationHandler<AdditionalAssemblyNotification>>(_ => CreateHandler());
logger.Debug(
$"Registered CQRS handler proxy for {typeof(INotificationHandler<AdditionalAssemblyNotification>).FullName}.");
}

/// <summary>
/// 创建一个仅供显式程序集注册路径使用的动态通知处理器。
/// </summary>
/// <returns>用于记录通知触发次数的测试替身处理器。</returns>
private static INotificationHandler<AdditionalAssemblyNotification> CreateHandler()
{
var handler = new Mock<INotificationHandler<AdditionalAssemblyNotification>>();
handler
.Setup(target => target.Handle(It.IsAny<AdditionalAssemblyNotification>(), It.IsAny<CancellationToken>()))
.Returns(() =>
{
AdditionalAssemblyNotificationHandlerState.RecordInvocation();
return ValueTask.CompletedTask;
});
return handler.Object;
}
}
148 changes: 0 additions & 148 deletions GFramework.Core.Tests/Architectures/ArchitectureContextTests.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
using System.Reflection;
using GFramework.Core.Abstractions.Architectures;
using GFramework.Core.Abstractions.Command;
using GFramework.Core.Abstractions.Enums;
using GFramework.Core.Abstractions.Environment;
using GFramework.Core.Abstractions.Ioc;
using GFramework.Core.Abstractions.Logging;
using GFramework.Core.Abstractions.Model;
using GFramework.Core.Abstractions.Query;
using GFramework.Core.Abstractions.Systems;
using GFramework.Core.Abstractions.Utility;
using GFramework.Core.Architectures;
using GFramework.Core.Command;
using GFramework.Core.Environment;
Expand Down Expand Up @@ -373,147 +369,3 @@ private sealed class TestCqrsRequest : IRequest<int>
{
}
}

#region Test Classes

public class TestSystemV2 : ISystem
{
private IArchitectureContext _context = null!;
public int Id { get; init; }

public void SetContext(IArchitectureContext context)
{
_context = context;
}

public IArchitectureContext GetContext()
{
return _context;
}

public void Initialize()
{
}

public void Destroy()
{
}

public void OnArchitecturePhase(ArchitecturePhase phase)
{
}
}

public class TestModelV2 : IModel
{
private IArchitectureContext _context = null!;
public int Id { get; init; }

public void SetContext(IArchitectureContext context)
{
_context = context;
}

public IArchitectureContext GetContext()
{
return _context;
}

public void Initialize()
{
}

public void OnArchitecturePhase(ArchitecturePhase phase)
{
}

public void Destroy()
{
}
}

public class TestUtilityV2 : IUtility
{
private IArchitectureContext _context = null!;
public int Id { get; init; }

public void SetContext(IArchitectureContext context)
{
_context = context;
}

public IArchitectureContext GetContext()
{
return _context;
}
}

public class TestQueryV2 : IQuery<int>
{
private IArchitectureContext _context = null!;
public int Result { get; init; }

public int Do()
{
return Result;
}

public void SetContext(IArchitectureContext context)
{
_context = context;
}

public IArchitectureContext GetContext()
{
return _context;
}
}

public class TestCommandV2 : ICommand
{
private IArchitectureContext _context = null!;
public bool Executed { get; private set; }

public void Execute()
{
Executed = true;
}

public void SetContext(IArchitectureContext context)
{
_context = context;
}

public IArchitectureContext GetContext()
{
return _context;
}
}

public class TestCommandWithResultV2 : ICommand<int>
{
private IArchitectureContext _context = null!;
public int Result { get; init; }

public int Execute()
{
return Result;
}

public void SetContext(IArchitectureContext context)
{
_context = context;
}

public IArchitectureContext GetContext()
{
return _context;
}
}

public class TestEventV2
{
public int Data { get; init; }
}

#endregion
Loading
Loading