1

VisualStudio11ベータ版で遊んでいます。

このコードを考えると:

namespace KC.DataAccess.Global
{
    /// <summary>Global methods for SQL access</summary>
    public static class SQL
    {    
        public async static void ExecuteNonQuery(string ConnStr, string Query)
        {
            if (string.IsNullOrEmpty(ConnStr)) throw new ArgumentNullException("ConnStr");
            if (string.IsNullOrEmpty(Query)) throw new ArgumentNullException("Query");
            SqlConnection conn = new SqlConnection(ConnStr);
            SqlCommand cmd = PrepSqlConnection(ref conn, Query);
            Exception exc = null;
            for (int i = 0; i < 3; i++)
                try { await Task.Run(() => cmd.ExecuteNonQuery()); break; }
                catch (Exception ex) { Thread.Sleep(50); exc = ex; }
            if (exc != null) throw new ApplicationException("Command failed after maximum attempts", exc);
            conn.Close();
            conn.Dispose();
         }
    } 
} 

これは非同期メソッドであるため、呼び出し元のメソッドに例外が発生することはないようです。したがって失敗するテストケースがあります。

using Target = KC.DataAccess.Global.SQL;
[TestMethod]
[TestCategory("Unit")]
[ExpectedException(typeof(ArgumentNullException))]
public void ExecuteNonQueryFail1()
{
    Target.ExecuteNonQuery(null, "select 1");
}

この場合、ExecuteNonQueryの検証部分は明らかに例外をスローしており、デバッグするとスローされることがわかります。

testメソッドをasyncに変更し、構文をTask.Run(()=> Target.ExecuteNonQuery())を待機するように変更しました。

質問:

  • ExecuteNonQueryは例外をスローしますか?
  • ExecuteNonQueryFail1に例外が表示されないのはなぜですか?
  • メソッドの非同期性を放棄することなく、例外を適切に処理してテストケースに合格するように、テストメソッドまたはメソッド自体を変更するにはどうすればよいですか?
4

2 に答える 2

4

VS11 Betaは、を返すテストメソッドをファーストクラスでサポートしていますTask

したがって、署名を次のように変更すると、次のようになります。

public async static Task ExecuteNonQuery(string ConnStr, string Query)

次に、そのようにテストできます。

using Target = KC.DataAccess.Global.SQL;
[TestMethod]
[TestCategory("Unit")]
[ExpectedException(typeof(ArgumentNullException))]
public async Task ExecuteNonQueryFail1()
{
  await Target.ExecuteNonQuery(null, "select 1");
}

(私はこの新しいサポートを自分で試す機会がありませんでしたが、これはうまくいくはずだと読みました)。

注:戻る必要がない限り(たとえば、イベントハンドラーの場合)、Taskメソッドに戻る必要があります。が待機可能であるため、コードはより再利用可能です。これについては、「AsyncandAwait」のイントロブログ投稿で取り上げています。asyncvoidTask

async void何らかの理由でメソッドをテストする必要がある場合は、例外をキャッチするために独自のメソッドを提供する必要があります( Stephen Toubの最近のブログ投稿のSynchronizationContext「非同期単体テスト」セクションを参照してください)。

特に非同期単体テストを扱ったブログ投稿がいくつかあります(パート1パート2)。VS2010 + AsyncCTPまたはVS11-DevPreviewの基本的な非同期単体テストプロジェクトを作成しましたが、VS11-Betaでまだテストする機会がありませんでした。async void必要に応じて、テストメソッドをユニット化する最も簡単な方法です。[CodePlex | NuGet]

于 2012-03-03T22:11:46.110 に答える
3

メソッドはを返すためvoid、例外が呼び出し元のコードにどのように伝播するかはわかりません。リターンタイプをに変更Taskすると、例外を監視できるようになりますが、明示的に行う必要があります。

呼び出しコードを変更する最良の方法は、を呼び出すことだと思いますWait()。のコードがTask例外Wait()をスローした場合、元の例外を含むをスローしAggregateExceptionます。

于 2012-03-03T13:36:12.213 に答える