3

データベース呼び出しに対して単体テストを作成していることに気付くのはごく普通のことですが、常に同じ問題が発生します。適切なクエリがデータベースに送信されているかどうかを検証するにはどうすればよいですか。

たとえば、次の形式でデータベースに最終更新を送信するこのクラスがあります。

update credential set password_hash = ?, password_crypt = ?, password_plain = ? where id = ?

password_plain(これはパスワード移行ツールです。フィールドのセキュリティ問題を気にしないでください)

このクラスのテストクラスを作成し、データベースアクセスクラスをモックし(この場合はSpring JDBCTemplateを使用しています)、発行されたSQLをキャプチャしました。SQLを取得したら、次のチェックを行います。

String space = "\\s+";
String optSpace = "\\s*";
String something = ".+";
String optSomething = ".*";

sql = sql.toLowerCase();
assertTrue(sql.matches(optSpace + "update" + space + "credential" + space + "set" + space + something));
assertTrue(sql.matches(something + space + "set" + space + optSomething + "password_hash" + optSpace + "=" + optSpace + "\\?" + something + "where" + something));
assertTrue(sql.matches(something + space + "set" + space + optSomething + "password_crypt" + optSpace + "=" + optSpace + "\\?" + something + "where" + something));
assertTrue(sql.matches(something + space + "set" + space + optSomething + "password_plain" + optSpace + "=" + optSpace + "\\?" + something + "where" + something));
assertTrue(sql.matches(something + space + "where" + space + optSomething + "id" + optSpace + "=" + optSpace + "\\?" + optSomething));

これらのチェックにより、発行されたSQLに次のような更新の最も重要な部分が含まれているかどうかを実際に検証しています。

  • 正しいテーブルが更新されています
  • 3つのフィールドすべてが、パラメーターとして渡された値に更新されています
  • はステートメントでid使用されており、その値はパラメーターです。where

発行されたクエリが上記の予想されるクエリであるかどうかを簡単に検証できますが、テストが制限されすぎて将来の変更ができなくなり、更新が正しい場合でも、クエリの一部が変更された場合は強制的に失敗します。テストは主に将来(ソフトウェアを変更していて、それに対してより安心が必要な場合)に使用されるように作成されており、現在では使用されないと思うので、このオプションを使用すると、テストは少し役に立たなくなります。

最後に、私の質問を宣言します。発行されたSQLを検証するためのより良いオプションはどれですか。

データベースを処理するクラスをテストするために、少量のデータで小さな組み込みデータベースを作成するプロジェクトがたくさんありますが、より純粋な単体テストの代替案を作成したいと思いました(それを呼び出すことができる場合)

4

3 に答える 3

2

実際のデータベースに対するテストに代わる良い方法はないと思います(たとえそれが埋め込まれていたとしても)。現時点では、SQL が構文的に有効であることをテストしていますが、実際には機能しますか? たとえば、制約などに違反するかどうか知っていますか...

モッキングなどはすべてうまくいっていますが、ある段階でデータベースに対してテストする必要があります。可能な場合はデータベースに対してテストしないようにしてから、弾丸を噛んで小さなデータベースの周りにテストを作成し(適切なロールバック/再構築などを使用して)、実際に正しいdb機能を確認します。

于 2013-02-19T00:01:41.883 に答える
1

SQLをアサートしないでください。それは無意味です。渡されたSQL文字列を別の文字列(これも自分で作成したため、検証は行われません)と比較することになります。そうでない場合は、独自のデータベースを実装する必要があります。代わりに、既存のものを使用してください。チェックは、クエリがデータベース内の正しいデータまたは正しく変更されたデータを返したことです。dbunitまたはsth同様のものを使用します。

于 2013-02-19T17:30:52.457 に答える
1

これらのテストの利点を再考していただきたいと思います。

  • 動作ではなく実装を検証しています
  • 将来 SQL クエリを変更した場合 (または誰かが無害なスペースを誤って追加した場合)、動作を維持していてもテストに失敗することになります。

最終的な DataAccessLayer については、統合テストを作成することをお勧めします。実際の最小限の DB に対して実行されるもの。確かにこれらのテストは遅くなりますが、提供される信頼性にはそれだけの価値があります。

したがって、GetCustomers() に対するテストを作成し、返された DTO に正しいデータが含まれていることを確認するのではなく、発行した SQL クエリが X であることを確認します。

于 2013-02-19T05:56:33.467 に答える