refactor(tests): 重构协程测试代码以改进类型安全性和构造函数参数

- 在CommandCoroutineExtensionsTests中使用模式匹配变量替换类型检查
- 为CoroutineSchedulerTests添加必要的依赖注入和模拟对象支持
- 移除CoroutineState枚举中的Held状态并调整相关测试断言
- 更新WaitForAllCoroutines构造函数调用以移除scheduler参数
- 修改WaitForCoroutine测试以提供必需的协程参数
- 添加WaitForEvent协程功能的完整测试实现
- 移除重复的构造函数重载测试用例
- [release ci]
This commit is contained in:
GeWuYou 2026-02-01 16:08:07 +08:00
parent ae37b8c5f1
commit 65fdea6c12
5 changed files with 131 additions and 46 deletions

View File

@ -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();

View File

@ -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
/// </summary>
private CoroutineScheduler _scheduler = null!;
/// <summary>
/// 测试用的简单事件类
/// </summary>
private class TestEvent
{
public string Data { get; set; } = string.Empty;
}
/// <summary>
/// 验证协程调度器创建时应该有正确的初始状态
/// </summary>
@ -292,6 +302,7 @@ public class CoroutineSchedulerTests
Assert.That(clearedCount, Is.EqualTo(0));
}
/// <summary>
/// 验证协程调度器应该正确处理协程异常
/// </summary>
@ -405,6 +416,46 @@ public class CoroutineSchedulerTests
Assert.That(executeCount, Is.EqualTo(1));
}
/// <summary>
/// 验证协程可以等待事件
/// </summary>
[Test]
public void Coroutine_Should_Wait_For_Event()
{
var timeSource = new TestTimeSource();
var scheduler = new CoroutineScheduler(timeSource);
// 创建模拟事件总线
var eventBusMock = new Mock<IEventBus>();
var unRegisterMock = new Mock<IUnRegister>();
Action<TestEvent>? eventCallback = null;
eventBusMock.Setup(bus => bus.Register<TestEvent>(It.IsAny<Action<TestEvent>>()))
.Returns(unRegisterMock.Object)
.Callback<Action<TestEvent>>(cb => eventCallback = cb);
TestEvent? receivedEvent = null;
var coroutine = CreateWaitForEventCoroutine<TestEvent>(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"));
}
/// <summary>
/// 创建简单的立即完成协程
/// </summary>
@ -451,6 +502,34 @@ public class CoroutineSchedulerTests
yield return new WaitOneFrame();
}
/// <summary>
/// 创建延迟协程
/// </summary>
private IEnumerator<IYieldInstruction> CreateDelayedCoroutine(Action callback, double delay)
{
yield return new Delay(delay);
callback();
}
/// <summary>
/// 创建等待另一个协程的协程
/// </summary>
private IEnumerator<IYieldInstruction> CreateWaitForCoroutine(IEnumerator<IYieldInstruction> targetCoroutine)
{
yield return new WaitForCoroutine(targetCoroutine);
}
/// <summary>
/// 创建等待事件的协程
/// </summary>
private IEnumerator<IYieldInstruction> CreateWaitForEventCoroutine<TEvent>(IEventBus eventBus,
Action<TEvent>? callback = null)
{
var waitForEvent = new WaitForEvent<TEvent>(eventBus);
yield return waitForEvent;
callback?.Invoke(waitForEvent.EventData!);
}
/// <summary>
/// 创建抛出异常的协程
/// </summary>

View File

@ -20,10 +20,9 @@ public class CoroutineStateTests
{
var values = Enum.GetValues<CoroutineState>();
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));
}
}

View File

@ -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<CoroutineHandle>();
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<ArgumentNullException>(() => new WaitForAllCoroutines(scheduler, null!));
}
/// <summary>
/// 验证WaitForAllCoroutines应该抛出ArgumentNullException当scheduler为null
/// </summary>
[Test]
public void WaitForAllCoroutines_Should_Throw_ArgumentNullException_When_Scheduler_Is_Null()
{
var handles = Array.Empty<CoroutineHandle>();
Assert.Throws<ArgumentNullException>(() => new WaitForAllCoroutines(null!, handles));
Assert.Throws<ArgumentNullException>(() => new WaitForAllCoroutines(null!));
}
/// <summary>
@ -148,7 +134,7 @@ public class WaitForAllCoroutinesTests
var handles = new List<CoroutineHandle> { 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<CoroutineHandle> { 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<CoroutineHandle> { 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<CoroutineHandle>();
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<CoroutineHandle>();
var wait = new WaitForAllCoroutines(scheduler, handles);
var wait = new WaitForAllCoroutines(handles);
Assert.That(wait, Is.InstanceOf<IYieldInstruction>());
}
@ -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<CoroutineHandle> { handle, handle };
var wait = new WaitForAllCoroutines(scheduler, handles);
var wait = new WaitForAllCoroutines(handles);
for (var i = 0; i < 12; i++) scheduler.Update();

View File

@ -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<IYieldInstruction>());
}
@ -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");
}
/// <summary>
/// 创建简单的立即完成协程
/// </summary>
private IEnumerator<IYieldInstruction> CreateSimpleCoroutine()
{
yield break;
}
}