【发布时间】:2017-03-21 12:16:56
【问题描述】:
目标:给未测试的外部代码一个超时。如果我的应用程序会导致对方死机,我想立即知道。假设这是非常复杂的单元测试。如果测试客户端使用了我的应用并在 500 毫秒内返回 - 它通过了,如果没有 - 它失败了。
所以是的,我不会对客户温柔,这是一个碰撞测试站点。我等待 500 毫秒,然后我不在乎客户端还在等待什么,我想立即将其崩溃并引发异常,但然后将其报告为测试结果。
可能是众多测试结果之一。
所以,现在,在这里,代码:
Console.Write("Testing");
try {
for (int j = 0; j < 3; j++) {
Console.Write(".");
for (int i = 0; i < 256; i++) {
using (var cts = new CancellationTokenSource(500)) {
var token = cts.Token;
token.Register(() => throw new TimeoutException("FREEZE DETECTED"));
clients.Add(LDSCheckAsync().Result);
}
}
clients.ForEach(i => i.Dispose());
clients.Clear();
}
Console.WriteLine("OK.");
}
catch {
clients.ForEach(i => i?.Dispose());
Console.WriteLine("FAIL!");
}
我设计的测试失败了。但我没有收到“失败”消息,我收到未处理的异常。
为什么,以及如何正确地做到这一点。在你尝试写评论之前,请考虑一下我不能在这里使用IfCancellationRequested 或类似的东西。被测函数通常会立即退出,但由于某些网络错误,它可能会进入 30 秒冻结。我完全不知道它何时发生,更不知道为什么。我做的测试应该可以帮助我诊断它。无法取消冻结。我知道。我想要的是将 freeze 转换为一个很好的可捕获异常,然后捕获它,然后记录它。但是当try / catch 没有按预期工作时(是的,即使在VS之外),我很无奈。
既然已经回答...
我制作了一个方便的工具,让我下次需要测试代码是否冻结时更轻松:
using System.Threading;
using System.Threading.Tasks;
namespace Woof.DebugEx {
public class FreezeTest {
private readonly Action Subject;
private int Timeout;
private bool IsDone;
public FreezeTest(Action subject) => Subject = subject;
public void Test(int timeout) {
Timeout = timeout;
var tested = new Task(Tested, null, TaskCreationOptions.LongRunning);
var watchdog = new Task(WatchDog, null, TaskCreationOptions.LongRunning);
tested.Start();
watchdog.Start();
Task.WaitAny(tested, watchdog);
if (!IsDone) throw new TimeoutException("FREEZE DETECTED.");
}
private void Tested(object state) {
Subject();
IsDone = true;
}
private void WatchDog(object state) => Thread.Sleep(Timeout);
}
}
现在我的测试片段如下所示:
Console.Write("Testing");
try {
for (int j = 0; j < 8; j++) {
Console.Write(".");
for (int i = 0; i < 16; i++) {
new FreezeTest(() => {
clients.Add(LDSCheckAsync().Result);
}).Test(100);
}
clients.ForEach(i => i.Close());
clients.Clear();
Thread.Sleep(1000);
}
Console.WriteLine("OK.");
}
catch {
clients.ForEach(i => i?.Dispose());
Console.WriteLine("FAIL!");
}
【问题讨论】:
-
什么是未处理的异常,是哪一行抛出的?
-
您能否提供有关未处理异常的信息?它在堆栈中的哪个位置被抛出?
-
@David:正好在“throw”行,没有调用堆栈。
-
@vtorola 正是它。除了明显的单线程片段。实际上它不是单线程的。主线程外抛出异常。
标签: c# unit-testing