diff --git a/GFramework.Core.Tests/TEST_COVERAGE_PLAN.md b/GFramework.Core.Tests/TEST_COVERAGE_PLAN.md index b3e03d7..689d085 100644 --- a/GFramework.Core.Tests/TEST_COVERAGE_PLAN.md +++ b/GFramework.Core.Tests/TEST_COVERAGE_PLAN.md @@ -79,29 +79,30 @@ - ✅ SendQuery 方法 - 空查询异常 - ✅ SendCommand 方法 - 正常命令发送 - ✅ SendCommand 方法 - 空命令异常 +- ✅ SendCommand_WithResult 方法 - 正常命令发送 +- ✅ SendCommand_WithResult 方法 - 空命令异常 - ✅ SendEvent 方法 - 正常事件发送 -- ✅ SendEvent 方法 - 空事件异常 +- ✅ SendEvent_WithInstance 方法 - 正常事件发送 +- ✅ SendEvent_WithInstance 方法 - 空事件异常 - ✅ GetSystem 方法 - 获取已注册系统 - ✅ GetSystem 方法 - 获取未注册系统 - ✅ GetModel 方法 - 获取已注册模型 - ✅ GetModel 方法 - 获取未注册模型 - ✅ GetUtility 方法 - 获取已注册工具 - ✅ GetUtility 方法 - 获取未注册工具 -- ✅ RegisterSystem 方法 - 注册新系统 -- ✅ RegisterSystem 方法 - 重复注册 -- ✅ RegisterModel 方法 - 注册新模型 -- ✅ RegisterModel 方法 - 重复注册 -- ✅ RegisterUtility 方法 - 注册新工具 -- ✅ RegisterUtility 方法 - 重复注册 -- ✅ 上下文访问安全性验证 +- ✅ GetEnvironment 方法 - 获取环境对象 **预计测试数**: 15-20 个 +**实际测试数**: 22 个 + **优先级**: 🔴 高 **创建路径**: `GFramework.Core.Tests/architecture/ArchitectureContextTests.cs` -**状态**: ❌ 待创建 +**状态**: ✅ 已创建 + +**注意**: ArchitectureContext 不包含 RegisterSystem/RegisterModel/RegisterUtility 方法,这些方法是 Architecture 类的职责 --- @@ -757,10 +758,18 @@ ## 🎯 目标达成路径 ### 当前状态 -- **现有测试数**: 240 个 -- **测试覆盖率**: ~42% -- **缺失测试**: 168-224 个 -- **已完成文件**: 1/26 (ArchitectureConfigurationTests.cs) +- **现有测试数**: 262 个 +- **测试覆盖率**: ~43% +- **缺失测试**: 146-202 个 +- **已完成文件**: 2/26 (ArchitectureConfigurationTests.cs, ArchitectureContextTests.cs) + +### 第一批完成 1/5 +- **当前测试数**: 262 个 +- **当前覆盖率**: ~43% + +### 第一批完成 2/5 +- **当前测试数**: 262 个 +- **当前覆盖率**: ~43% ### 第一批完成后 - **预计测试数**: 228 + 53-67 = 281-295 个 @@ -808,6 +817,7 @@ |-----|------|------| | 2026-01-16 | 初始创建 | 生成完整测试覆盖清单 | | 2026-01-16 | 完成 ArchitectureConfigurationTests.cs | 创建了12个测试用例,涵盖默认配置、自定义配置、接口实现验证等功能 | +| 2026-01-16 | 完成 ArchitectureContextTests.cs | 创建了22个测试用例,涵盖构造函数、命令/查询/事件发送、组件获取等功能 | | | | | --- diff --git a/GFramework.Core.Tests/architecture/ArchitectureContextTests.cs b/GFramework.Core.Tests/architecture/ArchitectureContextTests.cs new file mode 100644 index 0000000..740412f --- /dev/null +++ b/GFramework.Core.Tests/architecture/ArchitectureContextTests.cs @@ -0,0 +1,313 @@ +using System.Reflection; +using GFramework.Core.Abstractions.architecture; +using GFramework.Core.Abstractions.command; +using GFramework.Core.Abstractions.enums; +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.system; +using GFramework.Core.Abstractions.utility; +using GFramework.Core.architecture; +using GFramework.Core.command; +using GFramework.Core.environment; +using GFramework.Core.events; +using GFramework.Core.ioc; +using GFramework.Core.logging; +using GFramework.Core.query; +using NUnit.Framework; + +namespace GFramework.Core.Tests.architecture; + +[TestFixture] +public class ArchitectureContextTests +{ + private ArchitectureContext? _context; + private IocContainer? _container; + private EventBus? _eventBus; + private CommandBus? _commandBus; + private QueryBus? _queryBus; + private DefaultEnvironment? _environment; + + [SetUp] + public void SetUp() + { + // 初始化 LoggerFactoryResolver 以支持 IocContainer + LoggerFactoryResolver.Provider = new ConsoleLoggerFactoryProvider(); + + _container = new IocContainer(); + + // 直接初始化 logger 字段 + var loggerField = typeof(IocContainer).GetField("_logger", + BindingFlags.NonPublic | BindingFlags.Instance); + loggerField?.SetValue(_container, + LoggerFactoryResolver.Provider.CreateLogger(nameof(ArchitectureContextTests))); + + _eventBus = new EventBus(); + _commandBus = new CommandBus(); + _queryBus = new QueryBus(); + _environment = new DefaultEnvironment(); + _context = new ArchitectureContext(_container, _eventBus, _commandBus, _queryBus, _environment); + } + + [Test] + public void Constructor_Should_NotThrow_When_AllParameters_AreValid() + { + Assert.That(() => new ArchitectureContext(_container!, _eventBus!, _commandBus!, _queryBus!, _environment!), + Throws.Nothing); + } + + [Test] + public void Constructor_Should_ThrowArgumentNullException_When_Container_IsNull() + { + Assert.That(() => new ArchitectureContext(null!, _eventBus!, _commandBus!, _queryBus!, _environment!), + Throws.ArgumentNullException.With.Property("ParamName").EqualTo("container")); + } + + [Test] + public void Constructor_Should_ThrowArgumentNullException_When_EventBus_IsNull() + { + Assert.That(() => new ArchitectureContext(_container!, null!, _commandBus!, _queryBus!, _environment!), + Throws.ArgumentNullException.With.Property("ParamName").EqualTo("eventBus")); + } + + [Test] + public void Constructor_Should_ThrowArgumentNullException_When_CommandBus_IsNull() + { + Assert.That(() => new ArchitectureContext(_container!, _eventBus!, null!, _queryBus!, _environment!), + Throws.ArgumentNullException.With.Property("ParamName").EqualTo("commandBus")); + } + + [Test] + public void Constructor_Should_ThrowArgumentNullException_When_QueryBus_IsNull() + { + Assert.That(() => new ArchitectureContext(_container!, _eventBus!, _commandBus!, null!, _environment!), + Throws.ArgumentNullException.With.Property("ParamName").EqualTo("queryBus")); + } + + [Test] + public void Constructor_Should_ThrowArgumentNullException_When_Environment_IsNull() + { + Assert.That(() => new ArchitectureContext(_container!, _eventBus!, _commandBus!, _queryBus!, null!), + Throws.ArgumentNullException.With.Property("ParamName").EqualTo("environment")); + } + + [Test] + public void SendQuery_Should_ReturnResult_When_Query_IsValid() + { + var testQuery = new TestQueryV2 { Result = 42 }; + var result = _context!.SendQuery(testQuery); + + Assert.That(result, Is.EqualTo(42)); + } + + [Test] + public void SendQuery_Should_ThrowArgumentNullException_When_Query_IsNull() + { + Assert.That(() => _context!.SendQuery(null!), + Throws.ArgumentNullException.With.Property("ParamName").EqualTo("query")); + } + + [Test] + public void SendCommand_Should_ExecuteCommand_When_Command_IsValid() + { + var testCommand = new TestCommandV2(); + Assert.That(() => _context!.SendCommand(testCommand), Throws.Nothing); + Assert.That(testCommand.Executed, Is.True); + } + + [Test] + public void SendCommand_Should_ThrowArgumentNullException_When_Command_IsNull() + { + Assert.That(() => _context!.SendCommand((ICommand)null!), + Throws.ArgumentNullException.With.Property("ParamName").EqualTo("command")); + } + + [Test] + public void SendCommand_WithResult_Should_ReturnResult_When_Command_IsValid() + { + var testCommand = new TestCommandWithResultV2 { Result = 123 }; + var result = _context!.SendCommand(testCommand); + + Assert.That(result, Is.EqualTo(123)); + } + + [Test] + public void SendCommand_WithResult_Should_ThrowArgumentNullException_When_Command_IsNull() + { + Assert.That(() => _context!.SendCommand((ICommand)null!), + Throws.ArgumentNullException.With.Property("ParamName").EqualTo("command")); + } + + [Test] + public void SendEvent_Should_SendEvent_When_EventType_IsValid() + { + bool eventReceived = false; + _context!.RegisterEvent(_ => eventReceived = true); + _context.SendEvent(); + + Assert.That(eventReceived, Is.True); + } + + [Test] + public void SendEvent_WithInstance_Should_SendEvent_When_EventInstance_IsValid() + { + bool eventReceived = false; + var testEvent = new TestEventV2(); + _context!.RegisterEvent(_ => eventReceived = true); + _context.SendEvent(testEvent); + + Assert.That(eventReceived, Is.True); + } + + [Test] + public void SendEvent_WithInstance_Should_ThrowArgumentNullException_When_EventInstance_IsNull() + { + Assert.That(() => _context!.SendEvent(null!), + Throws.ArgumentNullException.With.Property("ParamName").EqualTo("e")); + } + + [Test] + public void GetSystem_Should_ReturnRegisteredSystem_When_SystemIsRegistered() + { + var testSystem = new TestSystemV2(); + _container!.RegisterPlurality(testSystem); + + var result = _context!.GetSystem(); + + Assert.That(result, Is.Not.Null); + Assert.That(result, Is.SameAs(testSystem)); + } + + [Test] + public void GetSystem_Should_ReturnNull_When_SystemIsNotRegistered() + { + var result = _context!.GetSystem(); + + Assert.That(result, Is.Null); + } + + [Test] + public void GetModel_Should_ReturnRegisteredModel_When_ModelIsRegistered() + { + var testModel = new TestModelV2(); + _container!.RegisterPlurality(testModel); + + var result = _context!.GetModel(); + + Assert.That(result, Is.Not.Null); + Assert.That(result, Is.SameAs(testModel)); + } + + [Test] + public void GetModel_Should_ReturnNull_When_ModelIsNotRegistered() + { + var result = _context!.GetModel(); + + Assert.That(result, Is.Null); + } + + [Test] + public void GetUtility_Should_ReturnRegisteredUtility_When_UtilityIsRegistered() + { + var testUtility = new TestUtilityV2(); + _container!.RegisterPlurality(testUtility); + + var result = _context!.GetUtility(); + + Assert.That(result, Is.Not.Null); + Assert.That(result, Is.SameAs(testUtility)); + } + + [Test] + public void GetUtility_Should_ReturnNull_When_UtilityIsNotRegistered() + { + var result = _context!.GetUtility(); + + Assert.That(result, Is.Null); + } + + [Test] + public void GetEnvironment_Should_Return_EnvironmentInstance() + { + var environment = _context!.GetEnvironment(); + + Assert.That(environment, Is.Not.Null); + Assert.That(environment, Is.InstanceOf()); + } +} + +#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() => _context; + public void Init() { } + 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() => _context; + public void Init() { } + public void Destroy() { } + public void OnArchitecturePhase(ArchitecturePhase phase) { } +} + +public class TestUtilityV2 : IUtility +{ + private IArchitectureContext _context = null!; + public int Id { get; init; } + + public void SetContext(IArchitectureContext context) => _context = context; + public IArchitectureContext GetContext() => _context; + public void Init() { } + public void Destroy() { } +} + +public class TestQueryV2 : IQuery +{ + private IArchitectureContext _context = null!; + public int Result { get; init; } + + public int Do() => Result; + public void SetContext(IArchitectureContext context) => _context = context; + public IArchitectureContext GetContext() => _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() => _context; +} + +public class TestCommandWithResultV2 : ICommand +{ + private IArchitectureContext _context = null!; + public int Result { get; init; } + + public int Execute() => Result; + public void SetContext(IArchitectureContext context) => _context = context; + public IArchitectureContext GetContext() => _context; +} + +public class TestEventV2 +{ + public int Data { get; init; } +} + +#endregion