我如何unit testing这种(正确)抛出exception的异步方法?

我在接口中有以下方法..

Task<SearchResult> SearchAsync(TU searchOptions); 

效果很好。

现在我正在尝试进行unit testing以测试出现问题的时间 – 并且代码会引发exception。

在这种情况下,我设置了我的方法来抛出HttpRequestException 。 我的unit testing未能说我扔了那个例外..

 var result = Should.Throw (async () => await service.SearchAsync(searchOptions)); 

来自unit testing的错误消息是

Shouldly.ChuckedAWobbly
var result =应该

System.Net.Http.HttpRequestException
但不是

所以断言框架说: 你期望一个例外,但没有一个被抛出。

当我逐步执行代码时,exception被100%抛出。

有人能看到我的unit testing代码出错了吗?

问题是您的断言框架不了解异步方法。 我建议你提出一个问题。

在此期间,您可以使用Should.Throw的源代码编写自己的MyShould.ThrowAsync

 public static async Task ThrowAsync(Func actual) where TException : Exception { try { await actual(); } catch (TException e) { return e; } catch (Exception e) { throw new ChuckedAWobbly(new ShouldlyMessage(typeof(TException), e.GetType()).ToString()); } throw new ChuckedAWobbly(new ShouldlyMessage(typeof(TException)).ToString()); } 

并使用它:

 var result = await MyShould.ThrowAsync (async () => await service.SearchAsync(searchOptions)); 

或稍微简单和等效:

 var result = await MyShould.ThrowAsync (() => service.SearchAsync(searchOptions)); 

unit testing异步代码/function非常困难。 我自己正在进行unit testing异步并遇到与你一样的问题。

我发现以下两个资源非常有用:

  • 异步编程的最佳实践 – 它深入研究了异步的主题以及测试它的问题。
  • unit testing以错误的方式异步并且unit testing以正确的方式异步 – 深入研究主题,显示您将遇到的问题以及如何设置测试。

问题是传递的lambda返回一个Task。 抛出的exception只能由Should.Throw观察,如果它等待完成此任务,显然它不会。 作为解决方法,您可以.Wait自己.Wait SearchAsync返回的任务。

mstest (内置的visual studio测试框架)支持自Visual Studio 2012以来的异步测试。您基本上只需通过“async Task”替换“void”来更改测试方法声明。

 [TestMethod] [ExpectedException(typeof(System.Net.Http.HttpRequestException))] public async Task SomeTest() { await service.SearchAsync(searchOptions); } 

您可能正在使用不同的unit testing框架,但目前尚不清楚哪一个。 请查阅其文档以查看它是否支持异步测试。

NUnit 2.6.3似乎也支持异步测试。

编辑 :所以你正在使用xUnit。 xUnit 2.0修复了这个特殊问题。 它目前仍然是阿尔法。

exception抛出在与运行unit testing的线程不同的线程上。 unit testing框架只能预测其自己的线程上的exception。

我建议你在同步版本的服务上测试exception。

像这样测试:

 var result = Should.Throw (() => service.SearchAsync(searchOptions).Result); 

要么:

 var result = Should.Throw (() => service.SearchAsync(searchOptions).Wait()); 

否则,您的Should.Throwasync lambda完成之前返回。