竞争条件的单元测试

时间:2016-11-04 18:04:21

标签: c# multithreading unit-testing thread-safety race-condition

考虑代码:

class TestClass
{
    private bool _someFlag;
    private object _sharedObject = new object();
    private readonly object _syncObject = new object();

    public object Read()
    {
        //lock (_syncObject)
        {
            _someFlag = false;
            return _sharedObject;
        }
    }

    public void Write(object obj)
    {
        //lock (_syncObject)
        {
            _someFlag = true;
            _sharedObject = obj;
        }
    }
}

它有竞争条件问题。当我们致电Read()时,某个主题可以在Write()_someFlag = false;行之间调用return _sharedObject;。我将通过lock运营商解决问题。但是,请你帮助我对这种竞争条件问题进行单元测试。

我不想将_someFlag更改为public用于测试目的或类似的任何内容。 我想做那样的事情:

[Fact]
public void RaceConditionTest()
{
    var correctObject = new object();
    var test = new TestClass();

    for (int i = 0; i < 1000; i++)
    {
        test.Write(correctObject);
        var assertTask = Task.Run(() =>
        {
            var actualObj = test.Read();
            Assert.True(object.ReferenceEquals(correctObject, actualObj), $"Failed on {i} iteration");
        });
        //Thread.Sleep(50);
        var failTask = Task.Run(() => test.Write(new object()));

        Task.WaitAll(assertTask, failTask);
    }
}

但我如何确保在assertTask之前启动failTask?或者也许有另一种方法对这种情况进行单元测试?提前谢谢。

3 个答案:

答案 0 :(得分:1)

要测试并发问题,最好让所有线程在定义的点等待,然后将它们全部释放。

var threadCount = someList.Length;
var threadsReady = new ManualResetEvent(false);
var threadsReadyCount = 0;   
Task.WhenAll(someList.Select(item => Task.Run(() => worker())));

void worker() {
    Interlocked.Increment(ref threadsReadyCount); 
    if (threadsReadyCount == threadCount)
        threadsReady.Set();
    else
        threadsReady.WaitOne();
    // Do some work...
}



         

答案 1 :(得分:0)

您可以在启动failTask​​之前检查assertTask是否正在运行或已完成:

while (assertTask.Status != Running && assertTask.Status != RanToCompletion)
Thread.Sleep(50);

答案 2 :(得分:0)

我一直坚持这种做法。但仍在寻找更好的方法...... 此测试在某些迭代中失败,但如果您取消注释git rebase -i HEAD~N 运算符,则将传递测试。

lock