如何处理xUnit .net的Assert.Throws 中的Tasks抛出的exception?
以下异步xUnit.net
测试使用标记有async
修饰符的lambda
失败,因为报告没有抛出exception:
[Theory, AutoWebData] public async Task SearchWithNullQueryThrows( SearchService sut, CancellationToken dummyToken) { // Fixture setup // Exercise system and verify outcome Assert.Throws(async () => await sut.SearchAsync(null, dummyToken)); // Teardown }
为了确保实际抛出ArgumentNullException
我明确地使用了try-catch
块。 它工作,但结果代码不干净(与第一次测试相比):
[Theory, AutoWebData] public async Task SearchWithNullQueryThrows( SearchService sut, CancellationToken dummyToken) { // Fixture setup var expected = typeof(ArgumentNullException); Type actual = null; // Exercise system try { await sut.SearchAsync(null, dummyToken); } catch (ArgumentNullException e) { actual = e.GetType(); } // Verify outcome Assert.Equal(expected, actual); // Teardown }
为什么带有用async
修饰符标记的lambda
的Assert.Throws
失败?
更新
这已在xUnit 2中解决,添加了Assert.ThrowsAsync
。
我怀疑Assert.Throws
不是async
Assert.Throws
。 我建议使用xUnit团队提出此问题,建议添加ThrowsAsync
。
在这种情况下, async
委托是返回Task
或Task
,并且ArgumentNullException
不会直接从委托中抛出; 相反,它被放置在Task
( Task.Exception.InnerException
)上。 Assert.Throws
期望exception直接从委托中抛出,而不是放在返回值的属性上。
您可以创建自己的AssertEx.ThrowsAsync
:
public static async Task ThrowsAsync(Func func) { var expected = typeof(TException); Type actual = null; try { await func(); } catch (Exception e) { actual = e.GetType(); } Assert.Equal(expected, actual); }
可以这样使用:
[Theory, AutoWebData] public async Task SearchWithNullQueryThrows( SearchService sut, CancellationToken dummyToken) { // Fixture setup // Exercise system and verify outcome await AssertEx.ThrowsAsync(async () => await sut.SearchAsync(null, dummyToken)); // Teardown }
我在MSTest中使用了类似的方法。
如果您还需要返回exception以进行validation,那么这可能很有用:
public static async Task AssertThrowsAsync(Func func) { var expected = typeof (TException); Exception exception = null; Type actual = null; try { await func(); } catch (Exception e) { actual = e.GetType(); exception = e; } Assert.NotNull(exception); Assert.Equal(expected, actual); return exception; }