2017-10-15 103 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