web-dev-qa-db-ja.com

Entity Frameworkでテストデータベースを使用するには、統合テストをどのように設定する必要がありますか?

アプリケーションの統合テストを作成していますが、統合スイートのテストデータベースをセットアップする方法に関するベストプラクティスを見つけることができませんでした。私は、EntityFrameworkコードファーストを使用してASP.NETMVC4アプリケーションに取り組んでいます。

テストプロジェクトのテストが、デフォルトでマシンのローカル開発データベースと通信していることを確認できます。テストを実行するたびに新しいデータベースが必要なため、これは理想的ではありません。

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

23
rouan

@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);
    }
}

私が見つけたものを追加する必要があります Entity Frameworkに関するこのブログ投稿 EntityFrameworkが内部で/慣例により何をしているのかをより深く理解するのに役立ちます。

24
rouan

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

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

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

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

次に、DBを作成するには、テストごとに1回、次のようにします。

    YourContext _ctx;

    [TestInitialize]
    public  void Initiaslise()
    {

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

        _ctx = new YourNameContext();

        initialiser.InitializeDatabase(_ctx);         
    }

そしてこれは各テストの終わりに削除します

    [TestCleanup]
    public  void Cleanup()
    {
        Database.Delete("YourName");
    }
6
Justin Harvey

NUnitを使用している場合は、Setup/Teardown属性をTransactionScopeとともに使用して、変更をデータベースにコミットしないようにすることができます。

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

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

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

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

5