17

私はアプリケーションの統合テストを作成しており、統合スイート用のテスト・データベースのセットアップ方法に関するベスト・プラクティスは見つかりませんでした。私はASP.NET MVC4アプリケーションで、Entity Frameworkのコードを使用して作業しています。Entity Frameworkでテストデータベースを使用するために、統合テストをどのようにセットアップする必要がありますか?

私のテストプロジェクトのテストは、デフォルトで自分のマシン上のローカル開発データベースと話していることが確認できます。これは理想的ではありません。テストを実行するたびに新しいデータベースを用意したいからです。

テストプロジェクトをセットアップして、テストが別のインスタンスと通信できるようにするにはどうすればよいですか? SQL Server Compact Editionインスタンスをセットアップすることは可能ですが、これを構成する方法がわかりません。

+0

ジミー・ボガードによるこの記事は、[統合テストでのデータベース・データの分離](http://lostechies.com/jimmybogard/2012/10/18/isolating-database-data-in-統合テスト/)。 –

答えて

21

あなたの答えは@Justinと@Petroに非常に感謝してくれました。私が思いついた解決策は、あなたが提案したテクニックの組み合わせです。以下で説明する解決策では、テストの実行ごとに新しいデータベースが提供され、テストごとに個別のトランザクションが提供されます。

私は私のテストプロジェクトのApp.configファイルで私のテストデータベースの接続文字列を追加しました:

<connectionStrings> 
    <add name ="TestDatabase" 
    providerName="System.Data.SqlClient" 
    connectionString="Data Source=(LocalDb)\v11.0;Database=TestDatabase;Integrated Security=True"/> 
    </connectionStrings> 

私はセットアップとティアダウンを提供するために、私の統合テストの基本クラスを作成しました。セットアップはコンテキストをインスタンス化し、まだ存在しない場合はDBを作成し、トランザクションを開始します。ティアダウンはトランザクションをロールバックします。

public class EntityFrameworkIntegrationTest 
{ 
    protected MyDbContext DbContext; 

    protected TransactionScope TransactionScope; 

    [TestInitialize] 
    public void TestSetup() 
    { 
     DbContext = new MyDbContext(TestInit.TestDatabaseName); 
     DbContext.Database.CreateIfNotExists(); 
     TransactionScope = new TransactionScope(TransactionScopeOption.RequiresNew); 
    } 

    [TestCleanup] 
    public void TestCleanup() 
    { 
     TransactionScope.Dispose(); 
    } 
} 

は最後に、私はすべてのテストが実行された後にデータベースを削除するの世話をするクラスがあります。

[TestClass] 
public static class TestInit 
{ 
    // Maps to connection string in App.config 
    public const string TestDatabaseName = "TestDatabase"; 

    [AssemblyCleanup] 
    public static void AssemblyCleanup() 
    { 
     Database.Delete(TestDatabaseName); 
    } 
} 

私は私が見つけたことを追加する必要がどのようなエンティティフレームワークをより深く理解するために有用this blog post about Entity Frameworkフードの下で/慣習によってやっている。

+1

私はDbContext.Database.CreateIfNotExists()を配置します。 [AssemblyInitialize]で返されたメソッドで – Elisabeth

+0

私のDbContextのコンストラクタに名前を渡すと何も起こりません。それでもデータベースのデフォルト設定が使用されます。なぜこれはあなたのためではなく、私にとってはうまくいくのですか?奇妙な。 –

+0

MyDbContextクラスはどこですか?それはどうですか? – Sonofblip

4

新しいDBインスタンスを指すユニットテストプロジェクトのapp.configに接続文字列を設定するだけです。

次に、テストクラスで初期化メソッドとクリーンアップメソッドを使用して、DBの作成と削除を行うことができます。

接続文字列は通常のものです。

<add name="UnitTestDBConnection" connectionString="Data Source=(local);Initial Catalog=UnitTestDB;Integrated Security=SSPI;" providerName="System.Data.SqlClient"/> 

そして、一度の試験につき、DBを作成するには、行うことができます:

YourContext _ctx; 

    [TestInitialize] 
    public void Initiaslise() 
    { 

     YourNameDbInitialise initialiser = new YourNameDbInitialiseForTest(); 
     Database.SetInitializer(initialiser); 

     _ctx = new YourNameContext(); 

     initialiser.InitializeDatabase(_ctx);   
    } 

、これをあなたはNUnitのを使用している場合は、各テスト

[TestCleanup] 
    public void Cleanup() 
    { 
     Database.Delete("YourName"); 
    } 
+0

ありがとうございます。これがどのように行われたかを示すあなたの答えにいくつかのコードを教えてください。新しいDBをどのように作成し、正しい接続文字列を提供する方法を確認しますか? – rouan

+1

上記の編集を参照してください –

3

の終わりに削除しますSetup/Teardown属性をTransactionScopeと使用して、データベースに変更をコミットしないことができます。

[SetUp] 
public void SetUp() 
{ 
    transaction = new TransactionScope(); 
} 

[TearDown] 
public void TearDown() 
{ 
    if(transaction != null) 
     transaction.Dispose(); 
} 

他のユニットテストフレームワークを使用している場合は、類似の属性を持つ必要があります。すべての統合テストフィクスチャに対して基本クラスDbItegrationTestを作成することをお勧めします。このクラスから派生すると、すべてのテストメソッドはデータベースへのコミットを行いません。

他のデータベースにEntity Frameworkを構成するには、テストアセンブリでdb接続文字列をオーバーライドしてください。

+1

テスト用に全く異なるデータベースを使用することをお勧めします。同じデータベースを使用すると、シードデータが含まれている可能性があり、テストの実行中にアプリが何らかの理由で使用されていると変更される可能性があります。別のデータベースを使用することで、マイグレーションが適切に動作していることをテストできるという利点もあります。 – rouan

+3

テストに別のデータベースを使用することができます。このためには、テストアセンブリのapp.configの接続文字列を更新するだけです。 MVCアプリケーションと同じ接続文字列名を使用しますが、データベース名/資格情報などを更新します。テストアセンブリにapp.configがない場合は、手動で追加できます。 –

関連する問題