以下异步xUnit.net
测试标有lambda
修饰符的async
因报告没有引发异常而失败:
[Theory, AutoWebData]
public async Task SearchWithNullQueryThrows(
SearchService sut,
CancellationToken dummyToken)
{
// Fixture setup
// Exercise system and verify outcome
Assert.Throws<ArgumentNullException>(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
}
为什么标有Assert.Throws<T>
修饰符的lambda
的{{1}}会失败?
答案 0 :(得分:36)
<强>更新强>
这已在xUnit 2中解决,添加了Assert.ThrowsAsync
。
我怀疑Assert.Throws
不是async
- 知道。我建议向xUnit团队提出此问题,建议添加ThrowsAsync
。
在这种情况下,async
委托正在返回Task
或Task<T>
,并且ArgumentNullException
不会直接从委托中退出;相反,它放在Task
(Task.Exception.InnerException
)上。 Assert.Throws
期望异常直接从委托中抛出,而不是放在返回值的属性上。
您可以创建自己的AssertEx.ThrowsAsync
:
public static async Task ThrowsAsync<TException>(Func<Task> 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<ArgumentNullException>(async () =>
await sut.SearchAsync(null, dummyToken));
// Teardown
}
我在MSTest中使用了类似的方法。
答案 1 :(得分:2)
如果您还需要返回异常以进行验证,那么这可能很有用:
public static async Task<Exception> AssertThrowsAsync<TException>(Func<Task> 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;
}