繁体   English   中英

如何使用NUnit使用异步单元测试来测试竞争条件?

[英]How to test race condition with async unit tests using NUnit?

这是我要测试的赛车条件代码,我有一个遗留代码,可以在一定程度上进行更改。 在我的主要函数中,我有一个函数可以返回我们等待的Task,另一个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中内置的一种同步机制-https ://docs.microsoft.com/zh-cn/dotnet/standard/threading/synchronizing-data-for-multithreading

另外,您可能会考虑使用由Stephen Cleary开发的一些异步友好的帮助器-https: //github.com/StephenCleary/AsyncEx

您也必须等待测试中的代码,否则,Aseert将在代码完成之前进行:

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

但是对我来说,这段代码有一些不足之处。 Task.Run有很多包装同步代码的Task.Run ,但现在不会带来任何好处。 同样, Sum也不是线程安全的,因此,如果在任何时间点, Sum都会被线程访问,则可能会发生并发的不良事件。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM