C# 如何使用NUnit通过异步单元测试测试竞争条件?

C# 如何使用NUnit通过异步单元测试测试竞争条件?,c#,multithreading,unit-testing,C#,Multithreading,Unit Testing,这是我要测试的赛车状态代码, 我有一个可以在一定程度上更改的遗留代码。 在我的主函数中,有一个函数返回我们等待的任务,还有一个函数用于UI,它不能被阻止,因为它运行在不同的线程上 在原始代码中,我们不关心结果,我们只是初始化一些类,我测试ViewModel是否为null 在我这里给出的示例代码中,我修改了代码以举例说明竞争条件的问题。 目前,我的测试将失败如何正确测试我的赛车状态 [TestClass] public class UnitTest1 { [Tes

这是我要测试的赛车状态代码, 我有一个可以在一定程度上更改的遗留代码。 在我的主函数中,有一个函数返回我们等待的任务,还有一个函数用于UI,它不能被阻止,因为它运行在不同的线程上

在原始代码中,我们不关心结果,我们只是初始化一些类,我测试ViewModel是否为null

在我这里给出的示例代码中,我修改了代码以举例说明竞争条件的问题。 目前,我的测试将失败如何正确测试我的赛车状态

 [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestMethod1()
        {
            Myclass tempClass = new Myclass();
            tempClass.CreateImage();
            Assert.AreEqual(3, tempClass.Sum);
        }
    }

    public class Myclass
    {
        public int Sum;

        public Myclass()
        {
            Sum = 0;
        }
        public async Task CreateImage()
        {
            await InternalFunction();
            await Task.Run(() => Physics());
        }

        public async Task InternalFunction()
        {
            await Task.Run(() =>
            {
                Math();
            });
        }

        public void Math()
        {
            Sum += 1;
        }

        public void Physics()
        {
            Sum += 2;
        }
    }

如果我运行测试,sum属性将是1,而不是预期的3。如何更改代码以执行
CreateImage()
函数的所有流程,并且仅在所有线程完成后,我希望断言TempClass的结果/内容。

CreateImage方法是异步的,但是您的单元测试方法不是,因此您的测试可以在CreateImage完成之前完成

您没有指定正在使用哪个版本的NUnit,但以下内容适用于最新版本的NUnit 3

[TestFixture]
public class UnitTest1
{
    [Test]
    public async Task TestMethod1()
    {
        Myclass tempClass = new Myclass();
        await tempClass.CreateImage();
        Assert.AreEqual(3, tempClass.Sum);
    }
}

当然,这假设<代码> MyClass <代码>是线程安全的-如果您的实际代码使用多个线程同时修改<代码> MyClass 实例的状态,那么您也可能需要考虑使用同步机制,如BCL—

中所构建的同步机制。

此外,您可以考虑使用Stephen Cleary开发的一些异步友好的帮助器-

,您也必须在测试本身中等待代码,否则AsieT将在代码完成之前发生:

        [TestMethod]
        public async Task TestMethod1()
        {
            Myclass tempClass = new Myclass();
            await tempClass.CreateImage();
            Assert.AreEqual(3, tempClass.Sum);
        }

但对我来说,这个代码有一些缺点。
任务中有很多包装同步代码。运行
不会像现在这样带来任何好处。另外,
Sum
不是线程安全的,因此,如果在任何时间点它将被线程访问,则可能会发生并发的错误

不清楚你在问什么。为什么不在单元测试中等待
CreateImage()
调用呢?这样,在所有操作完成之前,您不会执行断言。你到底有什么问题?你试过什么?“为什么不起作用?”彼得杜尼奥感谢我编辑问题的反馈。