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

Unit Test Synchronous Code has a Race Condition?

我已经在 git 中心上传了一些代码,可以在这里找到: 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); 行。

您的业务逻辑有问题:

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

DateTime.Now默认只有20ms左右的分辨率。这意味着您的消息早在 DateTime > since 为真之前就已收到。当您逐步执行代码时,时间会得到调整 - Send 在原始接收之后发生的时间要长得多。

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