書き方のユニットテストのためのデータベース電話
-
10-07-2019 - |
質問
私は近くの新しいプロジェクト(瞬!) 初めてのようにしているなどのユニット試験プロジェクトです。
うまく工夫の一部をユニットテストです。いくつかの方法をしていくのに十分な試験をパスの二つの値のチェックを期待しやすくなります。私にはその他の部品のコードとの複雑な走行に対し、クエリデータベースとなんなのかどのように試験します。
public DataTable ExecuteQuery(SqlConnection ActiveConnection, string Query, SqlParameterCollection Parameters)
{
DataTable resultSet = new DataTable();
SqlCommand queryCommand = new SqlCommand();
try
{
queryCommand.Connection = ActiveConnection;
queryCommand.CommandText = Query;
if (Parameters != null)
{
foreach (SqlParameter param in Parameters)
{
queryCommand.Parameters.Add(param);
}
}
SqlDataAdapter queryDA = new SqlDataAdapter(queryCommand);
queryDA.Fill(resultSet);
}
catch (Exception ex)
{
//TODO: Improve error handling
Console.WriteLine(ex.Message);
}
return resultSet;
}
この方法のほかに必要な全ての断片を取り出しデータベースからデータを返しますデータDataTableオブジェクトです。
最初の質問は、おそらく最も複雑な:どうしても試験状態ではこのような態度を取るのか。
その解決がはるかどうかという問題について模擬のデータベースの部品のみの試験に対する実際のDBです。
解決
何をテストしていますか
私の頭の上の3つの可能性があります:
A。 DAO(データアクセスオブジェクト)クラスをテストし、データベースに渡される値/パラメーターを正しくマーシャリングし、データベースから取得した結果を正しくマーシャリング/変換/パッケージ化することを確認しています。
この場合、データベースに接続する必要はまったくありません。データベース(またはJDBC、(N)Hibernate、iBatisなどの中間層)をモックに置き換える単体テストが必要です。
B。 (生成された)SQLの構文の正確さをテストしています。
この場合、SQLダイアレクトが異なるため、RDBMSのすべての癖をモックしようとするのではなく(機能を変更するRDBMSアップグレードを行うのではなく、RDBMSの正しいバージョンに対して(おそらく生成された)SQLを実行したい)テストによってキャッチされます)。
C。 SQLのセマンティックの正確さをテストしています。つまり、特定のベースラインデータセットに対して、操作(アクセス/選択、突然変異/挿入、更新)が期待される新しいデータセットを生成することです。
そのためには、dbunit(ベースラインを設定し、結果セットを期待される結果セットと比較することができます)のようなものを使用するか、ここで説明する手法を使用して、データベースで完全にテストを実行します: SQLクエリをテストする最良の方法。
他のヒント
これが、(IMHO)単体テストが開発者側に誤ったセキュリティの感覚を作り出すことがある理由です。データベースと通信するアプリケーションの私の経験では、エラーは通常、データが予期しない状態になった結果です(異常な値や欠損値など)。単体テストで日常的にデータアクセスのモックアップを作成すると、実際にはこの種のエラーに対して脆弱であるにもかかわらず、コードがうまく機能していると思うでしょう。
最善のアプローチは、テストデータベースを手軽に用意し、ゴツゴツしたデータの塊で満たし、それに対してデータベースコンポーネントテストを実行することだと思います。その間、ユーザーがデータを台無しにするよりもはるかに優れていることを忘れないでください。
単体テストのポイントは、単体で単体テスト(duh)することです。データベース呼び出しのポイントは、別のユニット(データベース)と統合することです。エルゴ:データベース呼び出しの単体テストは意味がありません。
ただし、統合テストデータベース呼び出しを行う必要があります(必要に応じて、単体テストに使用するものと同じツールを使用できます)。
神の愛のために、すでに存在しているライブデータベースに対してテストしないでください。しかし、あなたはそれを知っていました。
一般に、ユーザーを認証するか、電話帳/組織図のエントリを検索するかなど、各クエリが取得するデータの種類はすでにわかっています。関心のあるフィールドと、それらに存在する制約を知っています(たとえば、 UNIQUE
、 NOT NULL
など)。データベース自体ではなく、データベースと対話するコードを単体テストしているので、これらの機能をテストする方法について考えてください。フィールドが NULL
になる可能性がある場合、コードが NULL
値を正しく処理することを確認するテストが必要です。フィールドの1つが文字列( CHAR
、 VARCHAR
、 TEXT
、& c)である場合、エスケープされていることを確認してテストします文字を正しく。
ユーザーがデータベースに何かを入れようとし、それに応じてテストケースを生成しようとすると仮定します。このためにモックオブジェクトを使用する必要があります。
*望ましくない、悪意のある、または無効な入力を含む。
queryDA.Fill(resultSet);
queryDA.Fill(resultSet)
を実行するとすぐに、データベースをモック/偽造するか、統合テストを実行する必要があります。
1つは、統合テストが悪いとは思わないことです。異なる種類のバグをキャッチするだけで、偽陰性と偽陽性のオッズが異なるため、あまり頻繁に行われない可能性が高いです。とても遅いです。
このコードを単体テストしている場合、パラメーターが正しく構築されていることを検証します。コマンドビルダーは適切な数のパラメーターを作成しますか?それらはすべて価値がありますか? null、空の文字列、およびDbNullは正しく処理されますか?
データセットに実際にデータを入力すると、データベースがテストされます。これは、DALの範囲外の不安定なコンポーネントです。
厳密に言えば、データベースまたはファイルシステムの読み書きを行うテストは単体テストではありません。 (ただし、統合テストであり、NUnitまたはJUnitを使用して作成される場合があります)。単体テストは、単一のクラスの動作をテストして、その依存関係を分離することになっています。そのため、インターフェイスレイヤーとビジネスロジックレイヤーの単体テストを記述する場合、データベースはまったく必要ありません。
OK、しかし、どのようにデータベースアクセスレイヤーを単体テストしますか?この本のアドバイスが気に入っています: xUnitテストパターン(本のリンクを指します「DBを使用したテスト」の章。キーは次のとおりです。
- ラウンドトリップテストを使用する
- データアクセステストフィクスチャにあまり多くのテストを記述しないでください。「実際の」テストよりも実行がはるかに遅くなるためです。ユニットテスト
- 実際のデータベースでのテストを回避できる場合は、データベースなしでテストします
単体テストでは、通常、データベースをモックまたは偽造します。次に、依存性注入を介してモックまたは偽の実装を使用して、メソッドをテストします。また、データベース内の制約、外部キー関係などをテストする統合テストもおそらくあるでしょう。
テスト対象については、メソッドがパラメーターからの接続を使用していること、クエリ文字列がコマンドに割り当てられていること、返される結果セットが指定したものと同じであることを確認しますFillメソッドへの期待を介して。注-パラメーターを変更するFillメソッドよりも、値を返すGetメソッドをテストする方がおそらく簡単です。
そのためには、正しくない利用と依存関係の噴射(DI)。純いくつか存在します。私は現在使用し、統一の枠組みがありその他ります。
ここでは一からのリンクこのサイトではあるが、その他のもの依存性を注入す。純額とする。
このようにしていますが、簡単に模擬その他の部品のお申し込みだけで、模擬授業の実施はインタフェースできる方法を制御で対応いたします。でも、このもと設計へのインタフェース。
また最良の実践このことは、と思う。
それにならないdbのない限り、必要としております。
が必要な場合は試験のある特定の行動などの外部キー関係をカスケードを削除したい書データベース試験するものの、一般的になって現実のデータベースは、espで以上に一人が、単体テストまでの時間の場合において同じデータベースの試験に失敗してのデータは変更の可能性があります。
編集:によるデータベースユニット試験うことでもt-sqlをいくつかのセットアップ、試験以下のような基本的な決まり文句.http://msdn.microsoft.com/en-us/library/aa833233%28VS.80%29.aspx
JDBCベースのプロジェクトでは、JDBC接続をモックできるため、ライブRDBMSなしでテストを実行でき、各テストケースを分離できます(データの競合はありません)。
検証を可能にし、永続化コードは適切なクエリ/パラメーターを渡します(例: https://github.com/playframework/playframework/blob/master/framework/src/anorm/src/test/scala/anorm/ParameterSpec.scala )、JDBCの結果(解析/マッピング)を期待どおりに処理します(「データベースから一部のデータを抽出するために必要なビットとピースをすべて取り込み、DataTableオブジェクトにデータを返します」
)。jOOQや私のフレームワークAcolyteのようなフレームワークは、次の用途に使用できます。 https://github.com/cchantep/acolyte 。