diff --git a/GFramework.Core.Tests/coroutine/CommandCoroutineExtensionsTests.cs b/GFramework.Core.Tests/coroutine/CommandCoroutineExtensionsTests.cs index 29aadb1..0b71f94 100644 --- a/GFramework.Core.Tests/coroutine/CommandCoroutineExtensionsTests.cs +++ b/GFramework.Core.Tests/coroutine/CommandCoroutineExtensionsTests.cs @@ -86,9 +86,13 @@ public class CommandCoroutineExtensionsTests // 迭代协程直到完成 while (coroutine.MoveNext()) - if (coroutine.Current is WaitForTask) + { + if (coroutine.Current is WaitForTask waitForTask) + { // 等待任务完成 await Task.Delay(10); + } + } Assert.That(capturedException, Is.Null); } @@ -113,9 +117,13 @@ public class CommandCoroutineExtensionsTests // 迭代协程直到完成 while (coroutine.MoveNext()) - if (coroutine.Current is WaitForTask) + { + if (coroutine.Current is WaitForTask waitForTask) + { // 等待任务完成 await Task.Delay(10); + } + } Assert.That(capturedException, Is.Not.Null); // 异常被包装为 AggregateException @@ -144,9 +152,13 @@ public class CommandCoroutineExtensionsTests // 迭代协程直到完成 while (coroutine.MoveNext()) - if (coroutine.Current is WaitForTask) + { + if (coroutine.Current is WaitForTask waitForTask) + { // 等待任务完成 await Task.Delay(10); + } + } // 应该不会抛出异常 Assert.Pass(); @@ -192,7 +204,7 @@ public class CommandCoroutineExtensionsTests // 启动协程并等待命令执行完成 coroutine.MoveNext(); // 进入命令发送阶段 - if (coroutine.Current is WaitForTask) await Task.Delay(10); // 等待命令任务完成 + if (coroutine.Current is WaitForTask waitForTask) await Task.Delay(10); // 等待命令任务完成 // 此时协程应该在等待事件 Assert.That(coroutine.MoveNext(), Is.True); // 等待事件阶段 @@ -285,7 +297,7 @@ public class CommandCoroutineExtensionsTests // 启动协程 coroutine.MoveNext(); // 进入命令发送阶段 - if (coroutine.Current is WaitForTask) await Task.Delay(10); // 等待命令任务完成 + if (coroutine.Current is WaitForTask waitForTask) await Task.Delay(10); // 等待命令任务完成 // 触发事件 var testEvent = new TestEvent { Data = "TestData" }; @@ -328,7 +340,7 @@ public class CommandCoroutineExtensionsTests // 启动协程 - 命令失败时协程仍然继续 coroutine.MoveNext(); // 进入命令发送阶段 - if (coroutine.Current is WaitForTask) await Task.Delay(10); // 等待命令任务完成 + if (coroutine.Current is WaitForTask waitForTask) await Task.Delay(10); // 等待命令任务完成 // 命令执行失败后,协程继续执行 Assert.Pass(); diff --git a/GFramework.Core.Tests/coroutine/CoroutineSchedulerTests.cs b/GFramework.Core.Tests/coroutine/CoroutineSchedulerTests.cs index db2f9ce..73cf5f7 100644 --- a/GFramework.Core.Tests/coroutine/CoroutineSchedulerTests.cs +++ b/GFramework.Core.Tests/coroutine/CoroutineSchedulerTests.cs @@ -1,6 +1,8 @@ using GFramework.Core.Abstractions.coroutine; +using GFramework.Core.Abstractions.events; using GFramework.Core.coroutine; using GFramework.Core.coroutine.instructions; +using Moq; using NUnit.Framework; namespace GFramework.Core.Tests.coroutine; @@ -44,6 +46,14 @@ public class CoroutineSchedulerTests /// private CoroutineScheduler _scheduler = null!; + /// + /// 测试用的简单事件类 + /// + private class TestEvent + { + public string Data { get; set; } = string.Empty; + } + /// /// 验证协程调度器创建时应该有正确的初始状态 /// @@ -292,6 +302,7 @@ public class CoroutineSchedulerTests Assert.That(clearedCount, Is.EqualTo(0)); } + /// /// 验证协程调度器应该正确处理协程异常 /// @@ -405,6 +416,46 @@ public class CoroutineSchedulerTests Assert.That(executeCount, Is.EqualTo(1)); } + + /// + /// 验证协程可以等待事件 + /// + [Test] + public void Coroutine_Should_Wait_For_Event() + { + var timeSource = new TestTimeSource(); + var scheduler = new CoroutineScheduler(timeSource); + + // 创建模拟事件总线 + var eventBusMock = new Mock(); + var unRegisterMock = new Mock(); + + Action? eventCallback = null; + eventBusMock.Setup(bus => bus.Register(It.IsAny>())) + .Returns(unRegisterMock.Object) + .Callback>(cb => eventCallback = cb); + + TestEvent? receivedEvent = null; + var coroutine = CreateWaitForEventCoroutine(eventBusMock.Object, ev => receivedEvent = ev); + + var handle = scheduler.Run(coroutine); + + // 协程应该在等待事件,因此仍然存活 + Assert.That(scheduler.IsCoroutineAlive(handle), Is.True); + + // 触发事件 + var testEvent = new TestEvent { Data = "TestData" }; + eventCallback?.Invoke(testEvent); + + // 更新调度器 + scheduler.Update(); + + // 协程应该已完成,事件数据应该被接收 + Assert.That(scheduler.IsCoroutineAlive(handle), Is.False); + Assert.That(receivedEvent, Is.Not.Null); + Assert.That(receivedEvent?.Data, Is.EqualTo("TestData")); + } + /// /// 创建简单的立即完成协程 /// @@ -451,6 +502,34 @@ public class CoroutineSchedulerTests yield return new WaitOneFrame(); } + /// + /// 创建延迟协程 + /// + private IEnumerator CreateDelayedCoroutine(Action callback, double delay) + { + yield return new Delay(delay); + callback(); + } + + /// + /// 创建等待另一个协程的协程 + /// + private IEnumerator CreateWaitForCoroutine(IEnumerator targetCoroutine) + { + yield return new WaitForCoroutine(targetCoroutine); + } + + /// + /// 创建等待事件的协程 + /// + private IEnumerator CreateWaitForEventCoroutine(IEventBus eventBus, + Action? callback = null) + { + var waitForEvent = new WaitForEvent(eventBus); + yield return waitForEvent; + callback?.Invoke(waitForEvent.EventData!); + } + /// /// 创建抛出异常的协程 /// diff --git a/GFramework.Core.Tests/coroutine/CoroutineStateTests.cs b/GFramework.Core.Tests/coroutine/CoroutineStateTests.cs index 6524682..3b92b14 100644 --- a/GFramework.Core.Tests/coroutine/CoroutineStateTests.cs +++ b/GFramework.Core.Tests/coroutine/CoroutineStateTests.cs @@ -20,10 +20,9 @@ public class CoroutineStateTests { var values = Enum.GetValues(); - Assert.That(values, Has.Length.EqualTo(5), "CoroutineState should have 5 values"); + Assert.That(values, Has.Length.EqualTo(4), "CoroutineState should have 4 values"); Assert.That(values.Contains(CoroutineState.Running), Is.True, "Should contain Running"); Assert.That(values.Contains(CoroutineState.Paused), Is.True, "Should contain Paused"); - Assert.That(values.Contains(CoroutineState.Held), Is.True, "Should contain Held"); Assert.That(values.Contains(CoroutineState.Completed), Is.True, "Should contain Completed"); Assert.That(values.Contains(CoroutineState.Cancelled), Is.True, "Should contain Cancelled"); } @@ -36,14 +35,12 @@ public class CoroutineStateTests { var runningValue = (int)CoroutineState.Running; var pausedValue = (int)CoroutineState.Paused; - var heldValue = (int)CoroutineState.Held; var completedValue = (int)CoroutineState.Completed; var cancelledValue = (int)CoroutineState.Cancelled; Assert.That(runningValue, Is.EqualTo(0)); Assert.That(pausedValue, Is.EqualTo(1)); - Assert.That(heldValue, Is.EqualTo(2)); - Assert.That(completedValue, Is.EqualTo(3)); - Assert.That(cancelledValue, Is.EqualTo(4)); + Assert.That(completedValue, Is.EqualTo(2)); + Assert.That(cancelledValue, Is.EqualTo(3)); } } \ No newline at end of file diff --git a/GFramework.Core.Tests/coroutine/WaitForAllCoroutinesTests.cs b/GFramework.Core.Tests/coroutine/WaitForAllCoroutinesTests.cs index 3694aee..35f8028 100644 --- a/GFramework.Core.Tests/coroutine/WaitForAllCoroutinesTests.cs +++ b/GFramework.Core.Tests/coroutine/WaitForAllCoroutinesTests.cs @@ -36,7 +36,7 @@ public class WaitForAllCoroutinesTests scheduler.Run(coroutine2) }; - var wait = new WaitForAllCoroutines(scheduler, handles); + var wait = new WaitForAllCoroutines(handles); Assert.That(wait.IsDone, Is.False); } @@ -58,7 +58,7 @@ public class WaitForAllCoroutinesTests scheduler.Run(coroutine2) }; - var wait = new WaitForAllCoroutines(scheduler, handles); + var wait = new WaitForAllCoroutines(handles); scheduler.Update(); scheduler.Update(); @@ -87,7 +87,7 @@ public class WaitForAllCoroutinesTests scheduler.Run(coroutine3) }; - var wait = new WaitForAllCoroutines(scheduler, handles); + var wait = new WaitForAllCoroutines(handles); Assert.That(wait.IsDone, Is.False); Assert.That(executionCount, Is.EqualTo(0)); @@ -108,7 +108,7 @@ public class WaitForAllCoroutinesTests var scheduler = new CoroutineScheduler(timeSource); var handles = Array.Empty(); - var wait = new WaitForAllCoroutines(scheduler, handles); + var wait = new WaitForAllCoroutines(handles); Assert.That(wait.IsDone, Is.True); } @@ -119,21 +119,7 @@ public class WaitForAllCoroutinesTests [Test] public void WaitForAllCoroutines_Should_Throw_ArgumentNullException_When_Handles_Is_Null() { - var timeSource = new TestTimeSource(); - var scheduler = new CoroutineScheduler(timeSource); - - Assert.Throws(() => new WaitForAllCoroutines(scheduler, null!)); - } - - /// - /// 验证WaitForAllCoroutines应该抛出ArgumentNullException当scheduler为null - /// - [Test] - public void WaitForAllCoroutines_Should_Throw_ArgumentNullException_When_Scheduler_Is_Null() - { - var handles = Array.Empty(); - - Assert.Throws(() => new WaitForAllCoroutines(null!, handles)); + Assert.Throws(() => new WaitForAllCoroutines(null!)); } /// @@ -148,7 +134,7 @@ public class WaitForAllCoroutinesTests var handles = new List { scheduler.Run(coroutine) }; - var wait = new WaitForAllCoroutines(scheduler, handles); + var wait = new WaitForAllCoroutines(handles); scheduler.Update(); @@ -176,7 +162,7 @@ public class WaitForAllCoroutinesTests scheduler.Run(coroutine3) }; - var wait = new WaitForAllCoroutines(scheduler, handles); + var wait = new WaitForAllCoroutines(handles); scheduler.Update(); @@ -202,7 +188,7 @@ public class WaitForAllCoroutinesTests scheduler.Run(coroutine2) }; - var wait = new WaitForAllCoroutines(scheduler, handles); + var wait = new WaitForAllCoroutines(handles); Assert.That(wait.IsDone, Is.False); @@ -234,7 +220,7 @@ public class WaitForAllCoroutinesTests scheduler.Run(coroutine2) }; - var wait = new WaitForAllCoroutines(scheduler, handles); + var wait = new WaitForAllCoroutines(handles); scheduler.Pause(handles[0]); @@ -262,7 +248,7 @@ public class WaitForAllCoroutinesTests var coroutine = CreateDelayedCoroutine(() => { }, 1.0); var handles = new List { scheduler.Run(coroutine) }; - var wait = new WaitForAllCoroutines(scheduler, handles); + var wait = new WaitForAllCoroutines(handles); wait.Update(0.1); Assert.That(wait.IsDone, Is.False); @@ -282,7 +268,7 @@ public class WaitForAllCoroutinesTests var handles = new List { default }; - var wait = new WaitForAllCoroutines(scheduler, handles); + var wait = new WaitForAllCoroutines(handles); Assert.That(wait.IsDone, Is.True); } @@ -303,7 +289,7 @@ public class WaitForAllCoroutinesTests default }; - var wait = new WaitForAllCoroutines(scheduler, handles); + var wait = new WaitForAllCoroutines(handles); scheduler.Update(); @@ -323,7 +309,7 @@ public class WaitForAllCoroutinesTests var handles = new List(); for (var i = 0; i < 20; i++) handles.Add(scheduler.Run(CreateDelayedCoroutine(() => executionCount++, 1.0))); - var wait = new WaitForAllCoroutines(scheduler, handles); + var wait = new WaitForAllCoroutines(handles); Assert.That(wait.IsDone, Is.False); @@ -353,7 +339,7 @@ public class WaitForAllCoroutinesTests scheduler.Run(coroutine3) }; - var wait = new WaitForAllCoroutines(scheduler, handles); + var wait = new WaitForAllCoroutines(handles); scheduler.Update(); @@ -400,7 +386,7 @@ public class WaitForAllCoroutinesTests var scheduler = new CoroutineScheduler(timeSource); var handles = Array.Empty(); - var wait = new WaitForAllCoroutines(scheduler, handles); + var wait = new WaitForAllCoroutines(handles); Assert.That(wait, Is.InstanceOf()); } @@ -426,7 +412,7 @@ public class WaitForAllCoroutinesTests scheduler.Update(); scheduler.Update(); - var wait = new WaitForAllCoroutines(scheduler, handles); + var wait = new WaitForAllCoroutines(handles); Assert.That(wait.IsDone, Is.True); } @@ -444,7 +430,7 @@ public class WaitForAllCoroutinesTests var handle = scheduler.Run(coroutine); var handles = new List { handle, handle }; - var wait = new WaitForAllCoroutines(scheduler, handles); + var wait = new WaitForAllCoroutines(handles); for (var i = 0; i < 12; i++) scheduler.Update(); diff --git a/GFramework.Core.Tests/coroutine/YieldInstructionTests.cs b/GFramework.Core.Tests/coroutine/YieldInstructionTests.cs index 9264274..3c73231 100644 --- a/GFramework.Core.Tests/coroutine/YieldInstructionTests.cs +++ b/GFramework.Core.Tests/coroutine/YieldInstructionTests.cs @@ -292,7 +292,8 @@ public class YieldInstructionTests [Test] public void WaitForCoroutine_Should_Not_Be_Done_Initially() { - var wait = new WaitForCoroutine(); + var simpleCoroutine = CreateSimpleCoroutine(); + var wait = new WaitForCoroutine(simpleCoroutine); Assert.That(wait.IsDone, Is.False); } @@ -303,7 +304,8 @@ public class YieldInstructionTests [Test] public void WaitForCoroutine_Update_Should_Not_Affect_State() { - var wait = new WaitForCoroutine(); + var simpleCoroutine = CreateSimpleCoroutine(); + var wait = new WaitForCoroutine(simpleCoroutine); wait.Update(0.1); Assert.That(wait.IsDone, Is.False); @@ -373,7 +375,8 @@ public class YieldInstructionTests [Test] public void WaitForCoroutine_Should_Implement_IYieldInstruction_Interface() { - var wait = new WaitForCoroutine(); + var simpleCoroutine = CreateSimpleCoroutine(); + var wait = new WaitForCoroutine(simpleCoroutine); Assert.That(wait, Is.InstanceOf()); } @@ -416,4 +419,12 @@ public class YieldInstructionTests Assert.That(wait.IsDone, Is.True); Assert.That(callCount, Is.EqualTo(2), "Predicate should be called again after condition change"); } + + /// + /// 创建简单的立即完成协程 + /// + private IEnumerator CreateSimpleCoroutine() + { + yield break; + } } \ No newline at end of file