WPToolkitTestFx应用程序在异步void测试用例异常时崩溃



当标有"async"的测试用例失败时出现问题。应用程序只是崩溃在这种情况下,与未处理的异常TargetInvocationFail。据我所知,测试应用程序应该处理这些异常,因为在异常的情况下,它应该只是标记各自的情况为失败。这正是在正常的测试用例中发生的情况(没有async/await的东西在里面)。

我也为此创建了一个问题报告,请参阅http://phone.codeplex.com/workitem/10751。如果你有同样的问题,请给这个问题投票。如果你碰巧知道一些解决办法,请在这里告诉我。

EDIT:正如Stephen Cleary在评论中提到的,这个问题是由我的测试用例过程是async void而不是async Task引起的。我将把这个问题重新表述如下:为什么改变测试用例的返回类型会改变异常处理的行为?

一个好的一般准则是"避免async void "。其中一个原因是异常处理的不同:async Task方法将把任何异常放在它们返回的Task上,这可以在Taskawait时观察到。async void方法将直接在async void方法开始时当前的SynchronizationContext上引发异常。

另一件要记住的事情是async主要是一个编译器转换。如果你(或其他任何人)在运行时反射async Task方法,你只会看到一个返回类型为Task的方法;类似地,async void方法只有一个返回类型void

因此,当测试运行器看到一个返回void的方法(不知道它是一个async void方法)时,它执行它并看到它返回而不(直接)引发异常,因此它将其标记为"通过"。同时,由async void方法抛出的异常直接在SynchronizationContext上引发(大多数测试运行程序,包括MSTest,提供一个线程池SynchronizationContext),这个异常可能导致测试运行报告一个非特定的错误——或者如果测试运行完成得足够快,它可能被忽略。

现代测试运行器(包括VS2012的MSTest)通过检测Task的返回类型来理解async Task方法,并将等待Task完成,然后认为测试方法"完成"并将其标记为通过(或失败,如果返回的Task包含异常)。

我在我的博客上有MSTest中这种行为的例子(包括显示竞争条件的两个输出的屏幕截图),但请注意,这些博客条目几乎是一年前的,谈论的是使用VS2010的async单元测试。MSTest已在VS2012中更新,因此它对async Task方法具有合理的行为。

我们遇到的SL/WP工具包崩溃的主要问题是在测试失败后断言或调用TestComplete,或两次调用TestComplete引起的。示例:假设您用timeout属性标记了一个测试,并且您正在等待一个比超时时间更长的webrequest。如果webrequest没有失败,只是很慢,它仍然会在单元测试框架认为它完成后返回并调用TestComplete()。我不知道如何测试测试是否超时,所以我可以编写测试来防止这种情况,所以我建议在某些情况下不要使用它。

另一种情况是你等待两个事件,例如一个"完成"和一个"失败"事件,如果其中一个事件被引发,你做不同的事情,但它们都调用TestComplete:假设你的代码意外地引发了两个事件=>你刚刚调用了test complete,你的代码失败了。第三种情况是,您有一个共享对象,假设您没有在每个测试中重新创建一个WebClient实例:现在第一个测试侦听DownloadString并执行它的任务。下一个测试在运行时也开始侦听DownloadString,但由于旧的测试没有从它解挂,它的DownloadStringCompleted事件处理程序将再次运行,导致单元测试崩溃。

正如Stephen提到的,你不能在SL和WP单元测试框架中返回Task。我已经设法把它黑进了Silverlight单元测试运行器,您可以在这里阅读:http://www.sharpgis.net/post/2012/12/21/Hacking-the-Silverlight-Unit-Tests-to-support-returning-Task.aspx我也想为Windows Phone单元测试做同样的事情,但是源代码是不可用的,但是请在这里投票支持这个发布:http://phone.codeplex.com/workitem/10642

也请投票支持在单元测试框架中添加Task:http://phone.codeplex.com/workitem/10727 (WinPhone)和这里:http://silverlight.codeplex.com/workitem/11457 (Silverlight)

最新更新