Тестирование многопоточного кода может быть довольно грязным. Мой предпочтительный подход заключается в использовании ManualResetEvents для управления порядком выполнения. Обычно для этого требуется, чтобы у вас был какой-то способ применить код для тестирования, введя тестовый код или каким-либо другим способом.
Так что-то подобное должно дать согласованный результат теста:
SemaphoreSlim MySemaphore = new SemaphoreSlim(1, 1);
public ManualResetEventSlim BusinessLogicReached= new ManualResetEventSlim(false);
public ManualResetEventSlim BusinessLogicWaiting = new ManualResetEventSlim(false);
public bool InitializeUpdate()
{
// This instruction lets routine quit if lock is taken by other thread
if (!MySemaphore.Wait(0))
{
// if can not enter the lock
return false;
}
try
{
BusinessLogicReached.Set();
BusinessLogicWaiting.Wait();
return true;
}
finally
{
MySemaphore.Release();
}
}
[Test]
public void RunTest()
{
var updateTask = Task.Run(InitializeUpdate);
BusinessLogicReached.Wait();
Assert.IsFalse(InitializeUpdate()); // Semaphore taken
BusinessLogicWaiting.Set();
updateTask.Wait();
Assert.IsTrue(updateTask.Result);
Assert.IsTrue(InitializeUpdate()); // Semaphore released
}
* 1005 Тем не менее, эти виды тестов трудоемки в написании и обслуживании и не доказывают общей безопасности потоков, поэтому может быть более экономически эффективным сделать тщательный анализ кода многопоточного кода.