2012-12-29 44 views
18

async修飾子が付いlambdaと、次の非同期xUnit.netテストでは、例外がスローされなかったことを報告することによって失敗:xUnit .netのAssert.Throwsでタスクによってスローされた例外を処理する方法<T>?

[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ブロックを使用スローされることを確認するために。 lambdaAssert.Throws<T>async修飾子でマークされたのはなぜ

[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 
} 

は失敗します。それは、しかし、結果のコードは、(最初​​のテストと比較して)きれいではない働いていましたか?

+3

これは既知の問題です:http://xunit.codeplex.com/workitem/9799 – DaveShaw

+0

+1それリリース2.0.0-alphaが関連付けられているスナップショット「16883cb2351f」の前のスナップショット「03e3be9a6781」に修正されているようです。ただし、NuGet Package Managerを使用してソリューションを更新しても、それはまだ機能しません。 –

答えて

33

更新

これはAssert.ThrowsAsyncを添加し、xUnitフレーム2に解決されています。


私はAssert.Throwsasync -awareではないこと疑ういます。 xUnitチームにこの問題を提起して、ThrowsAsyncを追加することをお勧めします。

この場合asyncデリゲートはTaskまたはTask<T>、直接デリゲートから放り出されていないArgumentNullExceptionを返しています。代わりに、TaskTask.Exception.InnerException)に配置されます。 Assert.Throwsは、例外が直接デリゲートからスローされることを期待しています。戻り値のプロパティには配置されません。そのように使用することができます

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を中に同様のアプローチを使用し

あなたは自分のAssertEx.ThrowsAsyncなどを作成することができます。

+0

それは働いた:)ありがとう! –

+0

私はそれが 'ArgumentNullException 'だけが' Assert'にまで及ぶと信じていたので、少し修正しました。考慮すべきもう一つのことは、元の 'Assert.Throws' *が例外を返すということです(例外メッセージもテストすることができます)。 – Benjol

+0

https://gist.github.com/Haacked/4616366 – Benjol

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; 
    } 
関連する問題