使用nUnit进行死锁测试

7
我刚开始接触单元测试和nUnit(2.48)。我想编写一个测试方法,其中失败的情况是死锁。这有可能吗?显然,nUnit默认不知道该方法执行需要多长时间,所以我是否需要编写代码在单独的线程上执行工作,然后在超过我定义的某个时间后中止它并抛出异常?还有更好的方法吗?
谢谢
5个回答

7

当然,通过在另一个线程上运行代码并查看是否及时返回,可以测试死锁。这是一些(非常基本的)示例代码:

[TestFixture]
public class DeadlockTests
{
    [Test]
    public void TestForDeadlock()
    {
        Thread thread = new Thread(ThreadFunction);
        thread.Start();
        if (!thread.Join(5000))
        {
            Assert.Fail("Deadlock detected");
        }
    }

    private void ThreadFunction()
    {
        // do something that causes a deadlock here
        Thread.Sleep(10000);
    }
}

我不想说这是“最好的方法”,但在某些情况下,我发现它很有用。


如果连接在5001毫秒后发生怎么办? - bl4ckb0l7
这与停机问题无关。"及时完成"条款确保了这一点 :-)。这个测试的一个问题是它并没有真正测试死锁,它只运行一个测试线程。死锁通常发生在线程之间的交互中。 - Mendelt
1
当然,这不是一个完美的测试,但它很简单。在 thread.join 中,您指定了一个时间长度,如果没有死锁,这个时间应该足够运行您的代码。您并没有证明存在死锁,但对于这种类型的测试可能并不必要。 - Mark Heath
mendelt - 是的,在ThreadFunction中,你可能需要创建另一个线程。 - Mark Heath
2
啊,我现在明白你在做什么了。ThreadFunction本身创建了多个线程导致死锁。那么我们达成一致。它不会捕获所有的死锁,但可能会捕获一些... - Mendelt

5

虽然可能可行,但这并不是最好的做法。单元测试不太适合测试并发行为,不幸的是,没有太多适合的测试方法。

NUnit对线程没有任何限制。您可以编写测试来启动多个线程,然后测试它们的交互。但这些测试看起来更像是集成测试而不是单元测试。

另一个问题是死锁行为通常取决于线程调度的顺序。因此很难编写一个确定性的测试来测试某个死锁问题,因为您无法控制线程调度,这由操作系统完成。您可能会得到在多核处理器上有时失败但在单核处理器上始终成功的测试结果。


5

死锁检测等同于停机问题,因此在一般情况下无法解决。

如果您有特定的问题需要防范,可能会有特定的技巧来获得至少一定程度的安全性。请注意,这只能是一个技巧,永远不可能达到100%的安全性。例如,这样的测试可能在开发机器上始终通过,但在生产机器上却始终失败。


4

4
为了测试死锁,您必须在单元测试中实现状态图并检查当前状态图中的循环。状态图由资源作为节点和依赖项作为边组成。 我不知道如何实现这样的东西,但这是理论。 单元测试测试数据的输入和输出的正确性(主要是后者),而不是应用程序执行流程的正确性。 Mark Heath的想法似乎合理,但在学术上是错误的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接