优化测试用例等待与资源释放提升效率 缩短多处 Thread.Sleep/Task.Delay 等待时长,提高测试执行速度。日志相关测试改为轮询检测文件生成与内容写入,增强健壮性。DeferredQueueTests 增加 Commit 调用,确保资源释放。NetServerTests 优化客户端连接释放,增加超时与 finally 中 Stop/Dispose,防止资源泄漏。TimerXTests 等多处移除或缩短无用等待,缓存与 Add/Replace 测试超时设置同步优化,保证测试高效且稳定。石头 authored at 2026-09-01 16:22:05
diff --git a/XUnitTest.Core/Caching/ICacheContractTests.cs b/XUnitTest.Core/Caching/ICacheContractTests.cs
index 98ea733..72dafa1 100644
--- a/XUnitTest.Core/Caching/ICacheContractTests.cs
+++ b/XUnitTest.Core/Caching/ICacheContractTests.cs
@@ -75,7 +75,7 @@ public class ICacheContractTests
cache.Set(key, "will_expire", 1); // 1 秒过期
Assert.Equal("will_expire", cache.Get<String>(key));
- await Task.Delay(1500);
+ await Task.Delay(1100);
// 已过期,不应返回值
var val = cache.Get<String>(key);
Assert.Null(val);
diff --git a/XUnitTest.Core/Caching/MemoryCacheTests.cs b/XUnitTest.Core/Caching/MemoryCacheTests.cs
index 75557a3..91d60c8 100644
--- a/XUnitTest.Core/Caching/MemoryCacheTests.cs
+++ b/XUnitTest.Core/Caching/MemoryCacheTests.cs
@@ -77,8 +77,8 @@ public class MemoryCacheTests
var ic = Cache;
var key = "Name";
- ic.Set(key, Environment.UserName, 2);
- var rs = ic.Add(key, Environment.MachineName, 2);
+ ic.Set(key, Environment.UserName, 1);
+ var rs = ic.Add(key, Environment.MachineName, 1);
Assert.False(rs);
var name = ic.Get<String>(key);
@@ -87,14 +87,14 @@ public class MemoryCacheTests
var old = ic.Replace(key, Environment.MachineName);
Assert.Equal(Environment.UserName, old);
- ic.SetExpire(key, TimeSpan.FromSeconds(2));
+ ic.SetExpire(key, TimeSpan.FromSeconds(1));
name = ic.Get<String>(key);
Assert.Equal(Environment.MachineName, name);
Assert.NotEqual(Environment.UserName, name);
- Thread.Sleep(2000);
- rs = ic.Add(key, Environment.MachineName, 2);
+ Thread.Sleep(1100);
+ rs = ic.Add(key, Environment.MachineName, 1);
Assert.True(rs);
}
diff --git a/XUnitTest.Core/Log/LevelLogTests.cs b/XUnitTest.Core/Log/LevelLogTests.cs
index a79be8f..9bea7a5 100644
--- a/XUnitTest.Core/Log/LevelLogTests.cs
+++ b/XUnitTest.Core/Log/LevelLogTests.cs
@@ -30,8 +30,31 @@ namespace XUnitTest.Log
log.Error("error");
log.Fatal("fatal");
- // 等待日志落盘
- Thread.Sleep(2000);
+ // 日志通过线程池异步写入,通常毫秒级完成;轮询等待(兜底 5s 定时器刷盘路径)
+ var files = new[]
+ {
+ p + $"debug\\{DateTime.Today:yyyy_MM_dd}.log",
+ p + $"info\\{DateTime.Today:yyyy_MM_dd}.log",
+ p + $"warn\\{DateTime.Today:yyyy_MM_dd}.log",
+ p + $"error\\{DateTime.Today:yyyy_MM_dd}.log",
+ p + $"fatal\\{DateTime.Today:yyyy_MM_dd}.log",
+ };
+ var deadline = DateTime.Now.AddSeconds(6);
+ while (DateTime.Now < deadline)
+ {
+ var ok = true;
+ for (var i = 0; i < files.Length; i++)
+ {
+ if (!File.Exists(files[i].GetFullPath()))
+ {
+ ok = false;
+ break;
+ }
+ }
+ if (ok) break;
+
+ Thread.Sleep(50);
+ }
var f = p + $"debug\\{DateTime.Today:yyyy_MM_dd}.log";
Assert.True(File.Exists(f.GetFullPath()));
diff --git a/XUnitTest.Core/Log/TextFileLogTests.cs b/XUnitTest.Core/Log/TextFileLogTests.cs
index 0d7b388..13d6698 100644
--- a/XUnitTest.Core/Log/TextFileLogTests.cs
+++ b/XUnitTest.Core/Log/TextFileLogTests.cs
@@ -59,16 +59,35 @@ public class TextFileLogTests : IDisposable
var log = TextFileLog.Create(_logDir);
log.Info("TextFileLogTests: 测试写入消息");
- // 等待异步写入完成
- Thread.Sleep(6000);
+ // 日志通过线程池异步写入,通常毫秒级完成;轮询等待(兜底 5s 定时器刷盘路径)
+ var content = String.Empty;
+ var deadline = DateTime.Now.AddSeconds(6);
+ while (DateTime.Now < deadline)
+ {
+ var files = Directory.GetFiles(_logDir, "*.log");
+ if (files.Length > 0)
+ {
+ // 日志文件可能被TextFileLog持有锁,使用FileShare.ReadWrite读取
+ try
+ {
+ using var fs = new FileStream(files[0], FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
+ using var sr = new StreamReader(fs);
+ content = sr.ReadToEnd();
+ if (content.Contains("测试写入消息")) break;
+ }
+ catch (IOException) { }
+ }
+
+ Thread.Sleep(50);
+ }
- var files = Directory.GetFiles(_logDir, "*.log");
- Assert.True(files.Length > 0, "应生成日志文件");
+ var files2 = Directory.GetFiles(_logDir, "*.log");
+ Assert.True(files2.Length > 0, "应生成日志文件");
// 日志文件可能被TextFileLog持有锁,使用FileShare.ReadWrite读取
- using var fs = new FileStream(files[0], FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
- using var sr = new StreamReader(fs);
- var content = sr.ReadToEnd();
+ using var fs2 = new FileStream(files2[0], FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
+ using var sr2 = new StreamReader(fs2);
+ content = sr2.ReadToEnd();
Assert.Contains("测试写入消息", content);
}
diff --git a/XUnitTest.Core/Model/ActorTests.cs b/XUnitTest.Core/Model/ActorTests.cs
index d509082..61570ee 100644
--- a/XUnitTest.Core/Model/ActorTests.cs
+++ b/XUnitTest.Core/Model/ActorTests.cs
@@ -68,9 +68,6 @@ public class ActorTests
Assert.Equal(1000, actor.Total);
XTrace.WriteLine("TestCount End");
-
- Thread.Sleep(5000);
- XTrace.WriteLine("End");
}
private class TestActor : Actor
diff --git a/XUnitTest.Core/Model/DeferredQueueTests.cs b/XUnitTest.Core/Model/DeferredQueueTests.cs
index 2cf8a78..270e483 100644
--- a/XUnitTest.Core/Model/DeferredQueueTests.cs
+++ b/XUnitTest.Core/Model/DeferredQueueTests.cs
@@ -53,6 +53,11 @@ public class DeferredQueueTests
// 再次获取应返回同一对象
var obj2 = queue.GetOrAdd<TestObj>("key1");
Assert.Same(obj, obj2);
+
+ // GetOrAdd 借出的对象用完必须 Commit,否则销毁时等待 WaitForBusy。
+ // 两次 GetOrAdd 各借出一次,需按调用次数提交
+ queue.Commit("key1");
+ queue.Commit("key1");
}
[Fact(DisplayName = "GetOrAdd使用工厂方法")]
@@ -63,6 +68,9 @@ public class DeferredQueueTests
var obj = queue.GetOrAdd<TestObj>("key1", k => new TestObj { Name = k });
Assert.NotNull(obj);
Assert.Equal("key1", obj!.Name);
+
+ // GetOrAdd 借出的对象用完必须 Commit,否则销毁时等待 WaitForBusy
+ queue.Commit("key1");
}
[Fact(DisplayName = "Commit提交")]
@@ -97,6 +105,9 @@ public class DeferredQueueTests
queue.GetOrAdd<TestObj>("c");
Assert.True(queue.Times >= 3);
+
+ // GetOrAdd 借出的对象用完必须 Commit,否则销毁时等待 WaitForBusy
+ queue.Commit("c");
}
[Fact(DisplayName = "Name默认值")]
diff --git a/XUnitTest.Core/Net/NetSeverTests.cs b/XUnitTest.Core/Net/NetSeverTests.cs
index 35a9f64..1f5692f 100644
--- a/XUnitTest.Core/Net/NetSeverTests.cs
+++ b/XUnitTest.Core/Net/NetSeverTests.cs
@@ -34,19 +34,29 @@ namespace XUnitTest.Net
server.Start();
+ try
{
var uri = new NetUri($"tcp://127.0.0.1:{server.Port}");
- var client = new TcpClient();
- client.Connect(uri.EndPoint);
+ using (var client = new TcpClient())
+ {
+ // 设置接收超时,避免阻塞导致测试挂起
+ client.ReceiveTimeout = 3000;
- var ns = client.GetStream();
- ns.Write("Stone@NewLife.com".GetBytes());
+ client.Connect(uri.EndPoint);
- var buf = new Byte[1024];
- var rs = ns.Read(buf, 0, buf.Length);
- }
+ using var ns = client.GetStream();
+ ns.Write("Stone@NewLife.com".GetBytes());
- Thread.Sleep(3_000);
+ var buf = new Byte[1024];
+ var rs = ns.Read(buf, 0, buf.Length);
+ }
+ }
+ finally
+ {
+ // 确保停止并释放服务器,避免长期占用端口和后台资源
+ server.Stop("UnitTest");
+ server.TryDispose();
+ }
}
}
}
\ No newline at end of file
diff --git a/XUnitTest.Core/Threading/TimerXTests.cs b/XUnitTest.Core/Threading/TimerXTests.cs
index ea75ab0..cec4470 100644
--- a/XUnitTest.Core/Threading/TimerXTests.cs
+++ b/XUnitTest.Core/Threading/TimerXTests.cs
@@ -41,8 +41,6 @@ public class TimerXTests
Assert.False(timer.Async);
Assert.False(timer.Absolutely);
- Thread.Sleep(3050);
-
//Assert.Equal(10, count);
//Assert.Equal(10, timer.Timers);
}
@@ -57,7 +55,8 @@ public class TimerXTests
ms = ms + 100 - timer.NextTick;
Assert.InRange(ms, 0, 5);
- Thread.Sleep(1000);
+ // 留一点时间让定时器至少触发一次
+ Thread.Sleep(300);
}
private static void DoSyncTest(Object state)
@@ -80,7 +79,8 @@ public class TimerXTests
ms = ms + 100 - timer.NextTick;
Assert.InRange(ms, 0, 5);
- Thread.Sleep(1000);
+ // 留一点时间让定时器至少触发一次
+ Thread.Sleep(300);
}
private static async Task DoAsyncTest(Object state)
@@ -102,7 +102,8 @@ public class TimerXTests
var ms = timer.NextTick - Runtime.TickCount64;
Assert.InRange(ms, 0, 99);
- Thread.Sleep(1000);
+ // 留一点时间让定时器至少触发一次
+ Thread.Sleep(300);
}
private static async Task DoAbsolutelyTest(Object state)
@@ -126,10 +127,6 @@ public class TimerXTests
var ms = timer.NextTick - Runtime.TickCount64;
Assert.InRange(ms, 0, 3999 + 1000);
-
-#if DEBUG
- Thread.Sleep(5500);
-#endif
}
private static async Task DoCronTest(Object state)