nunit、assert.throwsも[expectionexception]キャッチスロー例外
質問
開始する前に、両方のソリューションをすでにチェックしていることを明確にしたいと思います この質問 と この質問.
テストする方法
public static DataSet ExecuteDataSet(this SqlConnection connection, string sql)
{
if (null == connection || null == sql)
{
throw new ArgumentNullException();
}
using (var command = connection.CreateCommand())
{
// Code elided for brevity
}
}
テスト方法
[Test]
[ExpectedException(typeof(ArgumentNullException))]
public void ExecuteDataSetThrowsForNullConnection()
{
((SqlConnection)null).ExecuteDataSet("SELECT TOP 1 * FROM prep");
}
[Test]
public void ExecuteDataSetThrowsForNullSql()
{
Assert.Throws<ArgumentNullException>(
() => Resource.Connection.ExecuteDataSet(null)
);
}
奇妙な動作
どちらのバージョンでもありません テスト メソッドがキャッチしています ArgumentNullException
それは入るとすぐに投げられます ExecuteDataSet
方法。コントロールフローは次の行に進みます(using (var command = connection.CreateCommand())
)そしてa NullReferenceException
代わりに発生しています(もちろん、これは私のテストケースのどちらも処理されません。 投げてはいけません).
もともと、最初のテスト方法(ExecuteDataSetThrowsForNullConnection
)2番目のもののように見えました(ExecuteDataSetThrowsForNullSql
)。いつ Assert.Throws
例外をキャッチできなかったので、私はいくつかの調査を行い、一部の人々が使用することを推奨したことに注意しました ExpectedException
代わりは。それに応じてテストコードを変更しましたが、役に立ちませんでした。
記録の場合、これは32ビット.NET 3.5コードで、ヌニット2.5.9でテストされています。 Visual Studio IntegrationにTestDriven.netを使用しており、NCOVERとNDependの最新バージョンをインストールしています。
TL; DR質問
テスト方法がスローされている例外をキャッチしないのはなぜですか、そしてそれを修正するにはどうすればよいですか?
編集
このバージョンのテストメソッドは機能します。
[Test]
public void ExecuteDataSetThrowsForNullConnection()
{
try
{
((SqlConnection)null).ExecuteDataSet("SELECT TOP 1 * FROM prep");
}
catch(ArgumentNullException e)
{
Assert.AreEqual(true, true);
}
catch (Exception e)
{
Assert.Fail("Expected ArgumentNullException, but {1} was thrown instead.", e.GetType().Name);
}
}
解決
私の推測では、あなたはあなたが思っているコードを実際にテストしていないということです。いくつか入れてみてください Console.WriteLine
声明とそれらが印刷されているかどうかを確認します。ブレークポイントを置いた場合 throw
デバッガーでステートメントとテストの実行、ブレークポイントはヒットしますか?コントロールが次の声明に渡されている場合、それは例外がスローされないことを意味します - それはおそらく、スロー方法で実行を続けることができる方法で捕まえることはできません。 本当 奇妙なCLRバグ。
私は書いた たくさん このようなコードで、ヌニットで失敗することはありません。
余談ですが、argumentExceptionsにパラメーター名を含めるのは良い練習だと思っているので、次のように書いています。
if (connection == null)
{
throw new ArgumentNullException("connection");
}
if (sql == null)
{
throw new ArgumentNullException("sql");
}
これには、コード内のパラメーター名を文字列として繰り返すという不幸な問題があります...しかし、それは適切に到達するのがかなり簡単です(特にresharperが名前を検証するのに役立つ場合)。 。 (他の方法で議論を検証するためのいくつかのグロッティハックがありますが、私はあなたがそれらを見たくないと思います...)