簡體   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