[英]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.