我在 .NET 平台上使用 Xunit 和 NMock。我正在测试一个方法是异步的表示模型。该方法创建一个异步任务并执行它,因此该方法立即返回并且我需要检查的状态还没有准备好。
我可以在不修改 SUT 的情况下在完成时设置一个标志,但这意味着我将不得不在一个 while 循环中继续检查标志,例如,可能会超时。
我有哪些选择?
我在 .NET 平台上使用 Xunit 和 NMock。我正在测试一个方法是异步的表示模型。该方法创建一个异步任务并执行它,因此该方法立即返回并且我需要检查的状态还没有准备好。
我可以在不修改 SUT 的情况下在完成时设置一个标志,但这意味着我将不得不在一个 while 循环中继续检查标志,例如,可能会超时。
我有哪些选择?
只是认为您可能需要对此进行更新,因为#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 ...
}
您的对象是否具有异步方法完成的任何类型的信号,例如事件?如果是这种情况,您可以使用以下方法:
[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 服务的方法的示例......