有没有办法对异步方法进行单元测试?

时间:2009-07-23 21:49:04

标签: .net unit-testing xunit.net nmock

我在.NET平台上使用Xunit和NMock。 我正在测试一个方法是异步的表示模型。 该方法创建一个异步任务并执行它,以便方法立即返回,我需要检查的状态尚未准备好。

我可以在完成时设置一个标志而不修改SUT但这意味着我必须继续检查while循环中的标志,例如,可能超时。

我有什么选择?

4 个答案:

答案 0 :(得分:47)

您可能想要对此进行更新,因为#1答案实际上是建议使用较旧的模式来解决此问题。

在.net 4.5 + xUnit 1.9或更高版本中,您只需返回一个Task,并可选择使用测试中的async关键字让xunit等待测试以异步方式完成。

请参阅xUnit.net 1.9

上的这篇文章
[Fact]
public async Task MyAsyncUnitTest()
{    
  // ... setup code here ...     
  var result = await CallMyAsyncApi(...);     
  // ... assertions here ...
}

答案 1 :(得分:20)

您的对象是否具有异步方法完成的任何信号,例如事件?如果是这种情况,您可以使用以下方法:

[Test]
public void CanTestAsync()
{
    MyObject instance = new MyObject()
    AutoResetEvent waitHandle = new AutoResetEvent(false); 
    // create and attach event handler for the "Finished" event
    EventHandler eventHandler = delegate(object sender, EventArgs e) 
    {
        waitHandle.Set();  // signal that the finished event was raised
    } 
    instance.AsyncMethodFinished += eventHandler;

    // call the async method
    instance.CallAsyncMethod();

    // Wait until the event handler is invoked
    if (!waitHandle.WaitOne(5000, false))  
    {  
        Assert.Fail("Test timed out.");  
    }  
    instance.AsyncMethodFinished -= eventHandler;    
    Assert.AreEqual("expected", instance.ValueToCheck);
}

答案 2 :(得分:4)

我首选的方法是模拟并注入实际的线程机制,以便在测试中它不是异步的。有时候这是不可能的(如果方法的线程是框架的一部分,或者不在你的控制之下)。

如果你无法控制线程创建,那么等待线程以某种方式完成,或者是一个while循环,或者只是一个定时等待线程应该采取多长时间,如果状态不是,则测试失败因为它花了太长时间。

答案 3 :(得分:2)

查看我关于单元测试Silverlight应用程序的文章

http://www.codeproject.com/KB/silverlight/Ag3DemoLOB.aspx

有一个单元测试方法的示例,该方法异步调用WCF服务...