2017-10-15 112 views
-1

這是我正在嘗試創建測試的代碼,
我有一個遺留代碼,我可以更改但在某種程度上。 在我的主要功能我有一個函數,它返回一個我們正在等待的任務。 和另一個函數,它不能被阻塞,因此它運行在不同的線程上。異步單元測試競爭條件

有沒有辦法讓單元測試通過,目前它會失敗。

在原始代碼中我們不關心結果,我們只是初始化一些類,並且我測試了viewmodel不是null。

我在這裏給出的示例代碼中,我更改了代碼來舉例說明競態條件的問題。

我也可以添加我使用Nunit而不是MStest如果這是相關的某種方式。

感謝

[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; 
     } 
    } 

如果我運行試驗,是失敗的總財產爲1,而不是3爲excpected。我希望瞭解如何將代碼更改爲能夠執行CreateImage()函數的所有流程,並且只有完成所有線程後,我才能斷言TempClass的結果/內容。

+0

目前還不清楚你在問什麼。你爲什麼不在單元測試中「等待」CreateImage()'調用?這樣,在所有操作完成之前,您不會執行斷言。你有什麼特別的困難?你有什麼?爲什麼沒有工作? –

+0

@PeterDuniho感謝我編輯我的問題的反饋。 – Gilad

回答

2

你將不得不等待測試自己的代碼爲好,否則代碼完成之前的Aseert將發生:

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

但對我來說這個代碼有一些pifalls。在Task.Run中有很多包裝同步代碼,因爲它現在不會帶來任何好處。另外Sum不是線程安全的,所以如果在任何時候它將被線程訪問併發的壞事情可能發生。

2

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/en-us/dotnet/standard/threading/synchronizing-data-for-multithreading

而且,你可能會考慮使用一些由斯蒂芬·克利裏研發的異步友好的助手 - https://github.com/StephenCleary/AsyncEx