【问题标题】:Crash in the WPToolkitTestFx app during exception in async void test case异步 void 测试用例异常期间 WPToolkitTestFx 应用程序崩溃
【发布时间】:2013-01-18 13:09:04
【问题描述】:

当标有“异步”的测试用例失败时,就会出现问题。在这种情况下,应用程序只是崩溃,出现未处理的 TargetInvocationFail 异常。据我了解,测试应用程序应该处理这些异常,因为如果出现异常,它应该将相应的情况标记为失败。这正是正常测试用例所发生的情况(其中没有 async / await 内容)。

我也为此创建了一个问题报告,请参阅http://phone.codeplex.com/workitem/10751。如果您有同样的问题,请点赞该问题。如果您碰巧知道一些解决方法,请在此处告诉我。

编辑:正如 Stephen Cleary 在评论中提到的那样,问题是由于我的测试用例过程是异步无效的,而不是异步任务引起的。那么我将这个问题重新表述如下:为什么改变测试用例的返回类型会改变异常处理的行为?

【问题讨论】:

  • 您没有在此处或在您的问题报告中发布复制代码。如果我猜测一下,我会说你的单元测试方法是async void,而它应该是async Task
  • 你没有问任何问题。你有吗?
  • @StephenCleary 你是绝对正确的,使东西 async Task 而不是 async void 解决了这个问题。我可以谦虚地请你回答为什么会这样吗?我将使用此信息编辑问题。

标签: c# unit-testing windows-phone-8 async-await


【解决方案1】:

一个好的一般准则是“避免async void”。造成这种情况的原因之一是异常处理的不同:async Task 方法将在其返回的Task 上放置任何异常,当Taskawaited 时可以观察到。 async void 方法将直接在 SynchronizationContext 上引发它们的异常,该 async void 方法启动时是当前的。

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

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

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

我有examples of this behavior in MSTest on my blog(包括显示竞争条件的两个输出的屏幕截图),但请注意,这些博客条目已经有将近一年的历史了,并且谈论了使用 VS2010 进行的async 单元测试。 MSTest 已使用 VS2012 进行了更新,因此它对 async Task 方法具有合理的行为。

【讨论】:

    【解决方案2】:

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

    另一种情况是,您等待两个事件,例如“完成”和“失败”事件,如果其中任何一个被引发,您会做不同的事情,但它们都调用 TestComplete:假设您的代码意外引发两个事件 => 你刚刚调用了测试完成并且你的代码失败了。 第三种情况是您有一个共享对象,假设您没有在每个测试中重新创建一个 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(银光)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-04
      • 2013-07-26
      • 1970-01-01
      • 1970-01-01
      • 2012-08-30
      • 2014-03-25
      相关资源
      最近更新 更多