lambda
修飾子でマークされたasync
を使用した次の非同期xUnit.net
テストは、例外がスローされなかったことを報告して失敗します。
[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
}
lambda
修飾子でマークされたasync
を含むAssert.Throws<T>
が失敗するのはなぜですか?
更新
これはxUnit2で解決され、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でも同様のアプローチを使用しています。
例外を返して確認する必要がある場合は、次のようにすると便利です。
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;
}