2013-12-21 24 views
5

ジェネリックリポジトリを模倣してすべてのサービスを単体テストする方法を学ぼうとしています。NHibernate Unit Mocking/In Memoryデータベースのテスト

public interface IRepository<TEntity> where TEntity : class 
{ 
    IQueryable<TEntity> GetAll(); 
    TEntity Get(int key); 
    void Insert(TEntity entity); 
    void Update(TEntity entity); 
    void Delete(int id); 
} 

そして、実際のリポジトリは以下のようになります。

マイリポジトリインタフェースがどのように見える(つまり、私がテストに興味はないんだけど)、依存関係のためにデータアクセスとNinjectを処理するためにNHibernateの流暢を使用して

イム:

public class GenerRepository<TEntity> : IRepository<TEntity>where TEntity : Entity 
{ 
    protected ISession Session{get { return NHibernateHelper.OpenSession(); }} 
    public IQueryable<TEntity> GetAll(){return Session.Query<TEntity>();} 
    public TEntity Get(int key){return Session.Get<TEntity>(key);} 
    public void Insert(TEntity entity){Session.Save(entity);} 
    public void Update(TEntity entity){Session.Update(entity);} 
    public void Delete(int id){Session.Delete(Session.Load<TEntity>(id));} 
} 

私のすべてのサービスは、作成されたリポジトリを取り入れて使用します。

私はこれを行う方法について非常に多くの記事を読んだことがありますが、どれも簡単ではなく、よく説明されています。だから、テスト用ジェネリックリポジトリの作成とそれを嘲笑することの間のアドバイス。私はメモリデータベースを作成することにも興味がありますが、実際のプロジェクトでコードを編集することなく、テストプロジェクトで流暢なnhibernateの設定をどのように設定するのですか?

ジェネリックリポジトリにデータベースまたはメモリデータベースではなくTentityのリストをヒットさせることは可能ですか?

お読みいただき、ありがとうございます。

+0

ことが可能です。このようにすれば、LINQプロバイダはLINQ 2 Objectsよりも制限されていることに注意してください。つまり、ユニットテストが 'List 'に合格し、データベースに対してクエリを実行するときにアプリケーションがクラッシュする可能性があります。 –

+0

ああ、ありがとう、ありがとう、私はこれをテストするためにアドバイスをお願いします。私に事例を教えてもらえますか? – LmC

+0

単体テストの純粋さに反しているかもしれませんが(単純な統合テストの領域が広がっているので)、通常は[メモリ内のSQLiteデータベース](http:// ayende。com/blog/3983/nhibernate-unit-testing)を参照してください。最新のNHibernateとドライバでは、(SQL Server上で動作している間に)SQLiteで失敗するNHibernate LINQクエリが1つもありませんでした。 –

答えて

4

これを達成するためのいくつかの方法がありますが、

  1. 利用のセットアップおよび再に使用してスクリプトをテストするための実際のデータベースこの方法を使用すると、データベースに変更があった場合にこれらのスクリプトを作成して維持する手間がかかります

  2. 実際のデータベースを使用し、テストにトランザクションスコープを使用しますテストを行い、一度トランザクションをロールバックするだけです)、これは本当に良いアプローチです。私はこれを大規模なプロジェクトに使用します。しかし、この問題の1つの問題は、テストを実行するのに多くの時間がかかります(約3500のテストがあり、それらをすべて実行するのに合計40分かかります)

  3. 偽のリポジトリ実際のリポジトリを使用してマッピングを検証します。このアプローチは、偽のリポジトリを作成し、維持するために追加の努力を必要とするでしょう。実際のリポジトリで実行された同じテストを偽のリポジトリで実行して、偽物が動作していることを確認することができます。このアプローチでは、テストの実行が高速になります。

4

私の答えは/おそらくコメントでなければなりません。あなたに伝えたいから:do not do。永続性から返されるデータの偽造を作成する時間を無駄にしないでください。そして、あなたの時間を投資しないでください。クライアントからデータを取り出し、それらをメモリ内のいくつかの仮想DBに入れます。

サービス(リポジトリを消費する)が実際のデータを実際にシリアライズ/レンダリングできることを確認する必要があります。そして、変更をデシリアライズ/永続化します。そしてそれは本当に本当のデータを必要とします。

テストデータを入力するためのスクリプトを作成するのに少し時間を費やします。あなたのテストで期待できるデータ:Ayende: NHibernate Unit Testingビジネスの検証サービスデータのシリアライズをやって...

もここで見てみましょう。抽出物は:

我々は、一般的な特性が持続されている唯一の三つのこと、 をテストしたいNHibernateはを使用して、そのカスケードは、期待どおりに動作し、その クエリが正しい結果を返します。それらのすべてを行うために、我々は は、一般的に、実際のデータベースと話をしなければならない、これらのどれかを偽造しようとするこのレベルの は無駄であり、非常に複雑になるだろう。

注:いくつかの時間前、私たちは、取引Begin()Rollback()のすべてのテストをラップするために使用されます。どちらが良い見ていた。しかし、私たちは、のためにのコールがであることが分かったため、すべてのテストが終了していませんでした。

+0

サウンドはどのようにして、Ninjectを使用してクラス内のISessioNFactoryオブジェクトを作成し、NHibernateHelperメソッドにバインドします。オブジェクトは静的です)、私のテストでは私の偽のISessionFactoryをあなたのリンクにどのように作成するのか記載していますか? – LmC

+0

重要なのは、リポジトリ(静的なセッションファクトリではない)を気にする必要があるということです。たとえば、GetAll()を使用してデータを取得する必要があるとしましょう。これは、テストスクリプトでDBに配置できないデータです。それから私たちは** IoC **から利益を得るべきです。新しいクラスのTestRepositoryを継承し、そこに 'GetAll()'の実装を変更します。この具体的なテストのために、* Ninject *にこの実装を使用する(またはパブリックセッター経由で渡す)よう教えます。しかし、通常のテストでは、**実際の**実装を使用します。 –

6

私はRadimに同意する必要があります。そのユニットは、ほとんどの場合、nhibernateの機能を模擬してnhibernateのコードをテストします。

あなたはNHibernateのを経由して取得したデータに基づいて、複雑なビジネスロジックをテストする場合を除き、これは完全に罰金です。

しかし、あなたのマッピング、データ検索と持続性が正常に動作かどうかをテストするために、あなたは本当のデータベースに対してテストする必要があります。

あなたはMSSQLサーバーをターゲットにする場合、私は、データベースの別のタイプを使用することはありません。代わりに、実サーバのすべての機能を備えたSQL Expressがあります。 MSSQL ExpressはオプションでローカルDBとともにインストールできます。これは私が統合テストのためにそれを使用し、それは本当に素晴らしい作品...あなたは多かれ少なかれ、MSSQL Serverのインスタンスをインスタンス化します接続文字列を経由してMDFファイルをロードするために

が可能になります。

  1. お使いのモデルによっては、あなたのユニットテストプロジェクト
  2. (コード最初/デシベル最初の)NHibernateのスキームを作成してみましょう、そうでない場合は、単純な移入方式でデータベースファイルを作成し、そのデータベースファイルに
  3. 追加ファイルが
  4. テスト対象のディレクトリにコピーされるように、テスト設定の展開項目にファイルをコピーしたデータベースファイルを使用して接続文字列を生成します。 例の接続文字列:Data Source=(LocalDB)\v11.0;AttachDbFileName=[whateverthepathis]\DatabaseFileName.mdf;InitialCatalog=DatabaseName;Integrated Security=True;MultipleActiveResultSets=True
  5. は、あなたのテストあなたのテストは、空のデータベースとするたびに実行されます

この方法を実行すると、あなたが作成する必要があります実サーバを必要とせずに再現可能な統合テストを持っていますDBまたはそれが毎回リセット...

関連する問題