web-dev-qa-db-ja.com

データアクセス層の単体テストの方法

C#でデータアクセスレイヤーをユニットテストする効果的な方法を探しています。私は主にa Java=開発者であり、C#を約6か月間しか使用していません。過去に、DBUnitと呼ばれるライブラリを使用して、既知の状態データベースに対してテストしました。使用できる同様のアクティブなライブラリを見つけることができ、最も近いのはnDBUnitのようですが、しばらくの間アクティブではありません。

C#には、方法と理由について多くの矛盾する方法があるようです。理想的には、データベースに接続せずにモックを使用してデータアクセスレイヤーをテストし、別のテストセットでストアプロシージャをユニットテストしたいと考えています。

私が取り組んでいるシステムでは、データアクセス層はADO.net(Entity Frameworkを使用せずに)を使用してSQL Serverのストアプロシージャを呼び出すことです。

以下は、私が作業しなければならないもののサンプルコードです。モックパスをたどるには、SqlCommand(IDbCommandを使用)をモックしたり、SqlConnectionをモックしたりする必要があります。

だから私の質問は、これを行うには(そのようなことがある場合)最良の方法と思われるものは何ですか?これまでの唯一の方法は、テスト用にモックされたSql *オブジェクトを返すことができるように、コンストラクターに渡されるProxyオブジェクトを作成することです。

まだ利用可能なすべてのC#モックライブラリを確認する機会がありませんでした。

public class CustomerRepository : ICustomerRepository
{
   private string connectionString;

   public CustomerRepository (string connectionString)
   {
     this.connectionString = connectionString;
   }

   public int Create(Customer customer)
   {

     SqlParameter paramOutId = new SqlParameter("@out_id", SqlDbType.Int);
     paramOutId.Direction = ParameterDirection.Output;
     List<SqlParameter> sqlParams = new List<SqlParameter>()
     {
       paramOutId,
       new SqlParameter("@name", customer.Name)
     }

     SqlConnection connection = GetConnection();
     try
     {
       SqlCommand command = new SqlCommand("store_proc_name", connection);

       command.CommandType = CommandType.StoredProcedure;

       command.Parameters.AddRange(sqlParams.ToArray());

       int results = command.ExecuteNonQuery();

       return (int) paramOutId.Value;
     }
     finally
     {
       CloseConnection(connection);
     }

   }

}
18
wenic

データベースを既知の状態にし、データベースに対してCustomerRepositoryを実行してCustomerRepositoryをテストできるツールを見つけることができないのは残念です。ただし、答えはすべてのADO呼び出しをモックアウトするためにモックを使用し始めることではありません。それにより、実際にはロジックをテストしない単体テストを作成することになります。それは単にコードが書かれているはずの方法で書かれていることをテストする。

SQLデータベースに顧客を作成するためのコマンドとしてSQL INSERTを作成するとします。ここで、customerテーブルにさまざまなフィールド(INSERTコマンドを壊す)が含まれるように変更を加え、ストアードプロシージャを使用してcustomerを作成するとします。モックを使用したテストは、テストを実施している実装が壊れている場合でも、合格します。さらに、ストアドプロシージャを使用するように実装を修正した場合、ユニットテストは失敗します。ユニットテストは、失敗するはずなのにパスし続けたが、システムを修正したときに失敗する場合のポイントは何ですか。

可能な代替案については この質問 を参照してください。マークされた答えは、実際にはIKVMを使用してC#でDBUnitを使用するだけであるようです。

したがって、探索を続ける別の方法があるかもしれませんが、ADO呼び出しをモックすると、重要なテストを実際には行わない、もろいテストにつながるだけです。

21
Mark Hildreth

この層の仕事は、コードをデータベースに接続することです。 db接続と構文に関する知識をカプセル化する必要があります。通常、ドメイン言語をデータベース言語にマップします。単体テストのこの部分を統合テストと見なし、データベーススキーマが実際のデータベースまたはテストデータベースと同等であることをテストします。主題の詳細 ここ

2
GalSegal

DataAccess Layerをテストするには、より複雑な構造が必要になります。

DataAccess Layerは、Repositoryオブジェクトから参照を呼び出します。 Repoオブジェクトは、UnitOfWorkデザインパターンを介してEntity Framework DbSetsから参照を呼び出します。

データアクセス層(TOP)
|
UnitOfWork
|
リポジトリパターンクラス
|
EFコンテキスト
|
実際のデータベース

構造を設定したら、リポジトリクラスをモックします。たとえば、アイテムはDBに挿入され、代わりにモックオブジェクトに移動します。後でモックオブジェクトに対してアサートして、アイテムが挿入されたかどうかを確認します。

リポジトリと作業ユニットのパターンの実装 をご覧ください。

1
hakan