单元测试同步代码有竞争条件吗?

时间:2017-04-12 07:59:23

标签: c# unit-testing race-condition

我在git hub上传了一些代码,可以在这里找到: https://github.com/Shaunus87/SyncTest包含我的原型代码和我的单元测试。

我基本上声明我的同步代码,挂钩事件,调用最终会调用事件的方法,并断言是否调用了事件:

        bool called = false;

        var testBinsToVend = GetRoboBins();
        var vendHelper = new VendingHelper(null, testBinsToVend, VendType.Issue);

        vendHelper.Complete += delegate () {
            called = true;
        };

        vendHelper.DoVending();

        Assert.IsTrue(called);

所有代码都是同步的(据我所知),但是如果我运行测试就会失败,如果我通过它进行调试,它会通过......

我尝试了一些事情,似乎要么a)我的代码是秘密异步并且我有竞争条件或b)在运行代码时它决定不执行一半的事件?

到底是什么?

修改 我也尝试过如下设置手动重置事件:

        bool called = false;
        var done = new ManualResetEvent(false);

        var testBinsToVend = GetRoboBins();
        var vendHelper = new VendingHelper(null, testBinsToVend, VendType.Issue);

        vendHelper.Complete += delegate () {
            called = true;
            done.Set();
        };

        vendHelper.DoVending();

        done.WaitOne();
        Assert.IsTrue(called);
        //was complete called?
        Assert.AreEqual(true, vendHelper.Bins.All(x => x.State != VendState.Pending));

但由于它是一行执行,当done.WaitOne();被命中时,测试永远不会到达Assert.IsTrue(called);行。

1 个答案:

答案 0 :(得分:2)

您的业务逻辑存在问题:

private CommCommand GetLastCommand(List<CommCommand> cmds, DateTime since) {
 return cmds.Where(x => x.DateTime > since)
            .OrderByDescending(x => x.DateTime)
            .FirstOrDefault();
}
默认情况下,

DateTime.Now的分辨率约为20毫秒左右。这意味着在DateTime > since成立之前很久就会收到您的消息。当您单步执行代码时,时间会得到调整 - Send在原始接收后发生的时间会更长。

您无法依靠DateTime.Now进行消息排序。它根本没有足够的准确性。如果你真的认为你可以依赖发送和接收订单的顺序(也就是说,机器在提示之前从不回复),而是用一个简单的计数器替换它。