有没有一种方法来单元测试异步方法?
问题描述:
我在.NET平台上使用Xunit和NMock。 我正在测试一个方法是异步的表示模型。 该方法创建一个异步任务并执行它,以便该方法立即返回,并且需要检查的状态尚未准备好。有没有一种方法来单元测试异步方法?
我可以在不修改SUT的情况下设置标志,但这意味着我必须在while循环中检查标志,例如可能超时。
我有什么选择?
答
您的对象是否具有异步方法完成的任何种类的信号,例如事件?如果是这样的话,你可以用下面的办法:
[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);
}
答
我的首选方法是模拟并注入实际的线程机制,以便在测试中它不是异步的。有些时候这是不可能的(如果方法的线程是框架的一部分,或者不在你的控制之下)。
如果你不能控制线程创建,那么等待线程以某种方式完成,或者是一个while循环,或者只是一个定时的等待,无论线程应该占用多长时间,并且如果状态为不在那里,因为反正花了太长时间。
答
看看我的文章单元测试Silverlight应用程序
http://www.codeproject.com/KB/silverlight/Ag3DemoLOB.aspx
有单元的实例测试调用一个方法WCF服务异步...
答
只是觉得你可能想要在这方面的更新,因为#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 ...
}
.NET不具备条件变量? – jrockway 2009-07-23 21:50:29
你想要测试什么? – 2009-07-23 22:00:08
有复杂的解决方案,但如果它只是一个测试,那么循环/超时/标志选项没有任何问题。 – Ray 2009-07-24 08:19:10