我如何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.Throw
在async
lambda完成之前返回。