From 085370aa27263008c978eda26658c9fc747ae83c Mon Sep 17 00:00:00 2001 From: GeWuYou <95328647+GeWuYou@users.noreply.github.com> Date: Sun, 1 Feb 2026 12:48:02 +0800 Subject: [PATCH] =?UTF-8?q?test(coroutine):=20=E6=B7=BB=E5=8A=A0=E5=8D=8F?= =?UTF-8?q?=E7=A8=8B=E6=89=A9=E5=B1=95=E5=92=8C=E5=8A=A9=E6=89=8B=E7=B1=BB?= =?UTF-8?q?=E7=9A=84=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 为 WaitForSecondsWithProgress 方法添加 null 回调参数的安全性测试 - 为 WaitForProgress 方法添加完整的功能和边界条件测试 - 为 RepeatCallForever 方法添加 shouldContinue 参数相关测试 - 为 RepeatCallForever 方法添加 CancellationToken 相关测试 - 移除未使用的 CreateCountingCoroutine 私有方法 - 使用 Assert.DoesNotThrow 确保 null 回调不会引发异常 --- .../coroutine/CoroutineExtensionsTests.cs | 38 ++-- .../coroutine/CoroutineHelperTests.cs | 172 ++++++++++++++++++ 2 files changed, 191 insertions(+), 19 deletions(-) diff --git a/GFramework.Core.Tests/coroutine/CoroutineExtensionsTests.cs b/GFramework.Core.Tests/coroutine/CoroutineExtensionsTests.cs index e9fe8ce..58b0afa 100644 --- a/GFramework.Core.Tests/coroutine/CoroutineExtensionsTests.cs +++ b/GFramework.Core.Tests/coroutine/CoroutineExtensionsTests.cs @@ -199,9 +199,9 @@ public class CoroutineExtensionsTests public void Sequence_Should_Execute_Coroutines_In_Order() { var executionOrder = new List(); - var coroutine1 = CreateCoroutineWithCallback(1, () => executionOrder.Add(1)); - var coroutine2 = CreateCoroutineWithCallback(2, () => executionOrder.Add(2)); - var coroutine3 = CreateCoroutineWithCallback(3, () => executionOrder.Add(3)); + var coroutine1 = CreateCoroutineWithCallback(() => executionOrder.Add(1)); + var coroutine2 = CreateCoroutineWithCallback(() => executionOrder.Add(2)); + var coroutine3 = CreateCoroutineWithCallback(() => executionOrder.Add(3)); var sequence = CoroutineExtensions.Sequence(coroutine1, coroutine2, coroutine3); @@ -397,14 +397,22 @@ public class CoroutineExtensionsTests [Test] public void WaitForSecondsWithProgress_Should_Handle_Null_Callback() { + // 测试传入null回调参数时不会抛出异常 var coroutine = CoroutineExtensions.WaitForSecondsWithProgress(1.0, null); - coroutine.MoveNext(); - coroutine.Current.Update(0.5); - Assert.That(coroutine.Current.IsDone, Is.False); + // 验证协程可以正常启动和执行 + Assert.That(coroutine, Is.Not.Null); - coroutine.Current.Update(0.5); - Assert.That(coroutine.Current.IsDone, Is.True); + // 执行协程并验证不会因为null回调而抛出异常 + Assert.DoesNotThrow(() => + { + coroutine.MoveNext(); + coroutine.Current.Update(0.5); + Assert.That(coroutine.Current.IsDone, Is.False); + + coroutine.Current.Update(0.5); + Assert.That(coroutine.Current.IsDone, Is.True); + }); } /// @@ -493,7 +501,7 @@ public class CoroutineExtensionsTests /// /// 创建简单的立即完成协程 /// - private IEnumerator CreateSimpleCoroutine() + private static IEnumerator CreateSimpleCoroutine() { yield break; } @@ -501,25 +509,17 @@ public class CoroutineExtensionsTests /// /// 创建带回调的协程 /// - private IEnumerator CreateCoroutineWithCallback(int id, Action callback) + private static IEnumerator CreateCoroutineWithCallback(Action callback) { yield return new WaitOneFrame(); callback(); } - /// - /// 创建计数协程 - /// - private IEnumerator CreateCountingCoroutine(int id, Action callback) - { - yield return new WaitOneFrame(); - callback(); - } /// /// 创建延迟协程 /// - private IEnumerator CreateDelayedCoroutine(Action callback, double delay) + private static IEnumerator CreateDelayedCoroutine(Action callback, double delay) { yield return new Delay(delay); callback(); diff --git a/GFramework.Core.Tests/coroutine/CoroutineHelperTests.cs b/GFramework.Core.Tests/coroutine/CoroutineHelperTests.cs index cf948ff..7efbfb0 100644 --- a/GFramework.Core.Tests/coroutine/CoroutineHelperTests.cs +++ b/GFramework.Core.Tests/coroutine/CoroutineHelperTests.cs @@ -335,4 +335,176 @@ public class CoroutineHelperTests { Assert.Throws(() => CoroutineHelper.WaitWhile(null!)); } + + /// + /// 验证WaitForProgress应该返回WaitForProgress实例 + /// + [Test] + public void WaitForProgress_Should_Return_WaitForProgress_Instance() + { + var wait = CoroutineHelper.WaitForProgress(1.0, _ => { }); + + Assert.That(wait, Is.InstanceOf()); + } + + /// + /// 验证WaitForProgress应该调用进度回调 + /// + [Test] + public void WaitForProgress_Should_Call_Progress_Callback() + { + var progressValues = new List(); + var wait = CoroutineHelper.WaitForProgress(1.0, progress => progressValues.Add(progress)); + + // 更新直到完成 + while (!wait.IsDone) wait.Update(0.1); + + Assert.That(progressValues.Count, Is.GreaterThan(0)); + // 进度值应该递增 + for (var i = 1; i < progressValues.Count; i++) + Assert.That(progressValues[i], Is.GreaterThanOrEqualTo(progressValues[i - 1])); + Assert.That(progressValues[^1], Is.EqualTo(1.0f).Within(0.01f)); + } + + /// + /// 验证WaitForProgress应该在指定时间后完成 + /// + [Test] + public void WaitForProgress_Should_Complete_After_Duration() + { + var wait = CoroutineHelper.WaitForProgress(1.0, _ => { }); + + wait.Update(0.5); + Assert.That(wait.IsDone, Is.False); + + wait.Update(0.5); + Assert.That(wait.IsDone, Is.True); + } + + /// + /// 验证WaitForProgress应该在零持续时间时抛出ArgumentException + /// + [Test] + public void WaitForProgress_Should_Throw_ArgumentException_When_Zero_Duration() + { + Assert.Throws(() => CoroutineHelper.WaitForProgress(0, _ => { })); + } + + /// + /// 验证WaitForProgress应该在负数持续时间时抛出ArgumentException + /// + [Test] + public void WaitForProgress_Should_Throw_ArgumentException_When_Negative_Duration() + { + Assert.Throws(() => CoroutineHelper.WaitForProgress(-1.0, _ => { })); + } + + /// + /// 验证WaitForProgress应该在null回调时抛出ArgumentNullException + /// + [Test] + public void WaitForProgress_Should_Throw_ArgumentNullException_When_Null_Callback() + { + Assert.Throws(() => CoroutineHelper.WaitForProgress(1.0, null!)); + } + + /// + /// 验证RepeatCallForever应该在shouldContinue返回false时停止 + /// + [Test] + public void RepeatCallForever_Should_Stop_When_ShouldContinue_Returns_False() + { + var callCount = 0; + var maxCalls = 3; + var coroutine = CoroutineHelper.RepeatCallForever(0.1, () => callCount++, () => callCount < maxCalls); + + while (coroutine.MoveNext()) coroutine.Current.Update(0.1); + + Assert.That(callCount, Is.EqualTo(maxCalls)); + } + + /// + /// 验证RepeatCallForever应该在shouldContinue初始返回false时不执行 + /// + [Test] + public void RepeatCallForever_Should_Not_Execute_When_ShouldContinue_Initially_False() + { + var callCount = 0; + var coroutine = CoroutineHelper.RepeatCallForever(0.1, () => callCount++, () => false); + + Assert.That(coroutine.MoveNext(), Is.False); + Assert.That(callCount, Is.EqualTo(0)); + } + + /// + /// 验证RepeatCallForever应该处理null shouldContinue(无限执行) + /// + [Test] + public void RepeatCallForever_Should_Execute_Forever_When_ShouldContinue_Is_Null() + { + var callCount = 0; + var coroutine = CoroutineHelper.RepeatCallForever(0.1, () => callCount++, (Func?)null); + + for (var i = 0; i < 5; i++) + { + Assert.That(coroutine.MoveNext(), Is.True); + coroutine.Current.Update(0.1); + } + + Assert.That(callCount, Is.EqualTo(5)); + Assert.That(coroutine.MoveNext(), Is.True); + } + + /// + /// 验证RepeatCallForever应该在CancellationToken取消时停止 + /// + [Test] + public void RepeatCallForever_Should_Stop_When_CancellationToken_Cancelled() + { + var callCount = 0; + using var cts = new CancellationTokenSource(); + var coroutine = CoroutineHelper.RepeatCallForever(0.1, () => + { + callCount++; + if (callCount >= 3) cts.Cancel(); + }, cts.Token); + + while (coroutine.MoveNext()) coroutine.Current.Update(0.1); + + Assert.That(callCount, Is.EqualTo(3)); + } + + /// + /// 验证RepeatCallForever应该在CancellationToken已取消时不执行 + /// + [Test] + public void RepeatCallForever_Should_Not_Execute_When_CancellationToken_Already_Cancelled() + { + var callCount = 0; + using var cts = new CancellationTokenSource(); + cts.Cancel(); + var coroutine = CoroutineHelper.RepeatCallForever(0.1, () => callCount++, cts.Token); + + Assert.That(coroutine.MoveNext(), Is.False); + Assert.That(callCount, Is.EqualTo(0)); + } + + /// + /// 验证RepeatCallForever应该正常执行当CancellationToken未取消时 + /// + [Test] + public void RepeatCallForever_Should_Execute_When_CancellationToken_Not_Cancelled() + { + var callCount = 0; + using var cts = new CancellationTokenSource(); + var coroutine = CoroutineHelper.RepeatCallForever(0.1, () => callCount++, cts.Token); + + for (var i = 0; i < 5; i++) + { + Assert.That(coroutine.MoveNext(), Is.True); + coroutine.Current.Update(0.1); + } + + Assert.That(callCount, Is.EqualTo(5)); + } } \ No newline at end of file