-
10-07-2019 - |
質問
以前にこの質問をしました私のDALを正しく単体テストする方法、答えられないまま残っていることの1つは、実際にDALをテストする場合、テストDBを使用することです。次に、モックとテストDBの役割は何ですか?
これを追加するために、別の人が<!> quot;単体テストの終了時にトランザクションを使用してロールバックすることを提案しました。そのため、dbはclean <!> quot;です。 DALをテストするためのこのテスト+テストDB +トランザクションロールバック(DBは実際には記述されていない)アプローチについてどう思いますか?
完了するために、私のDALはEntity Frameworkで構築されており、DBにはストアドプロシージャがありません。 EFは非常に新しいため、DALをテストして正しく機能することを確認する必要があります。
解決
たとえば、制約、トリガー、自動インクリメント列など、データベース構造によって実施されているロジックをチェックするために、いくつかの統合テストを行うことをお勧めします。ただし、ユニットテストでは、フレームワークコンポーネントDALが(ユニットテストで)必要に応じて依存しているのは、コーディングしたコンポーネントのみをテストすることです。 SqlCommandやSqlConnection(たとえば)でメソッドをテストする必要はありません。使用するフレームワークコンポーネントが機能し、既知のデータ(良い、悪い、例外)をメソッドに返すスタブまたはモックを作成して、メソッドが正しく機能することを確認する必要があります。モックなしで、データベース内のデータを生成し、それが正しいことを確認する責任があります。また、ネットワーク、データベース自体などの依存関係を開いたままにしておくと、テストが不安定になる可能性があります。
また、単体テストでは、他のタイプのテストの必要性はなくなりません。統合テストと受け入れテストはまだ有効であり、実行する必要があります。おそらく単体テストと同じ頻度で行う必要はなく、単体テストでコード品質が向上するほど広範囲である必要はないかもしれませんが、単体テストは魔法の弾丸ではありません。
他のヒント
データアクセスコードをテストするとき、モックはあまり役に立ちませんでした。単体テストの目的は、データベース関連のコードが機能することを確認することであり、データベースをモックするとテストが妨げられます。
ビジネスコードをテストするとき、モッキングは確かに有用になります。データベース呼び出しをモックして、テストデータを返し、そのような状況でのビジネスロジックの動作を検証できます。
トランザクションの使用について-アーキテクチャにテストの開始時にトランザクションを開始する余地があり、そのトランザクション内でユニットテストのデータベース関連の呼び出しをすべて実行する限り、確かに可能です。ただし、試したことはありません。
ユニットテストをロールバックするトランザクションに入れると、ハッキングのように聞こえます。 その代わりに、テストを実行する前に(つまり、テストクラスのコンストラクターで)あらゆるデータベース(静的/参照データではないもの)をクリーンアップするコードがあります。テストが失敗した場合、データベースにデータを保持しておくと、失敗の原因を調べるのに役立ちます。
トランザクションユニットテストを使用しており、Hibernateマッピングの問題を数回防止しました。それ以外の場合-単体テストとは何ですか? List<Item> getAllItems()
のように些細なことですか? :)
テストデータベースを使用すると、データベース自体またはDALとデータベース間の通信パス(ネットワークなど)で問題が発生する可能性が広がります。モックはそれらの可能性を排除します。
DBの状態を考慮する必要があるだけでなく、可用性もあります。 DBがオフラインの場合、DALテストのすべてが失敗するのはなぜですか?
テストする必要があるのは、DALが正しいコマンドを発行して、作成/取得/更新/削除することです。このためにSQLを実行する必要はありません。オブジェクト永続化フレームワークを使用して、正しい指示を与えることを確認するだけです。
ただし、アプリをテストするだけではありません。また、構成とストアドプロシージャおよびビューをテストしています。これらはユニットテストで文書化されています。
問題は元の質問にある可能性が非常に高いです。 MVCのより一般的な例のいくつかは、次のようなDbSet
を返すことでショートカットを使用します。
public class MusicStoreEntities : DbContext
{
public DbSet<Album> Albums { get; set; }
public DbSet<Genre> Genres { get; set; }
public DbSet<Artist> Artists { get; set; }
public DbSet<Cart> Carts { get; set; }
public DbSet<Order> Orders { get; set; }
public DbSet<OrderDetail> OrderDetails { get; set; }
}
これは、これが悪いことだと思う永続性の実装と密接に結びついています。簡単にモックできるList<t>
を返す方が良いでしょう。