在 .NET 中,有什么方法可以测试 Async Lock,以证明重入已被阻止?

In .NET what is a way to test an Async Lock, proving that reentrancy is prevented?

假设我有一个想要测试的方法:

public async Task ConnectAsync()
{
    using (await _connectMutex.LockAsync())
    {
        await Task.Delay(1000);
    }
}

我对直接测试锁不感兴趣(我相信 AsyncLock 的开发者知道他在做什么)。相反,我想要 demonstrate/prove 的是,如果我同时使用 3 个线程调用此方法,则总测试执行时间将 >= 3 秒。我的问题很简单:如何安排这样的测试?

您不应该使用锁周围的方法来测试锁。如果要测试锁直接测试锁:

public async Task TestAsync()
{
    using (await _connectMutex.LockAsync())
    using (await _connectMutex.LockAsync())
}

假设这是您的锁定实现。如果它是外部的,则将其留给开发人员,否则您将需要测试 everything.

如果您的异步锁具有同步授予锁(如果可用)的语义(这是一个合理的假设),那么您可以这样测试它:

[TestMethod]
public void PreventsReentrancy()
{
  var mutex = ...;
  var firstLock = mutex.LockAsync();
  var secondLock = mutex.LockAsync();

  Assert.IsTrue(firstLock.IsCompleted);
  Assert.IsFalse(secondLock.IsCompleted);
}

编辑更新问题:

what I wanted to demonstrate/prove was that if I hit this method with 3 threads simultaneously, that the total test execution time will be >= 3 seconds. My question is simply: how would one arrange such a test?

首先,我会仔细检查确实您想要测试的内容。由于这是我的AsyncLock,我可以说已经有单元测试验证互斥和防止可重入锁。我真的非常强烈地避免对任何与时间相关的内容进行单元测试。

但是如果你实际上想要做一个有时间要求的单元测试,我建议首先挂钩 Task.Delay 方法(例如,使用 Microsoft Fakes)和将其替换为使用 Rx 的 IScheduler 而不是计时器的实现。然后你可以使用 Rx 的 TestScheduler 来验证时序行为。