2

Entity Framework の単体テストに関するいくつかの質問と回答を読んだ後、統合テストのための単体テストを控えることにしました。私は、EF コンテキストとのやり取りは「プライベート」アクションであるという哲学を取り入れています。これは、サービスとは別に単体テストを行う必要がなく、簡単かつ正確に嘲笑することができないためです。

注: 私の例では、EF5 を使用しています。

まず、ユーザーを作成するためのサービス メソッドがあります。

void CreateUser(string username, string password);

テスト アセンブリには、データベース (EF Code First) とテスト データを作成する SetUpFixture (テスト実行用に 1 回のみ) があります。

[SetUpFixture]
public class SetUpFixture
{
    [SetUp]
    public void SetUp()
    {
        using (var context = new MyDbContext())
        {
            Database.SetInitializer(new DropCreateDatabaseAlways<MyDbContext>());

            // Set up a bunch of initial data and commit
        }
    }
}

次に、各テストの前に、TestFixtureSetup メソッドが実行され、DB コンテキストのインスタンスが作成されます。これは、(各テストの後) 破棄されるとロールバックするように設定され、サービスのインスタンスも作成されます。

[TestFixtureSetUp]
public virtual void TestFixtureSetUp()
{
    _context = new MyContext(rollbackOnDispose: true);
    UserService = new SignupService(_context);
}

[TestFixtureTearDown]
public virtual void TestFixtureTearDown()
{
    Context.Dispose();
}

最後に、有効なデータが渡されたことを確認するための実際の統合テスト、ユーザー名のレコードが作成されたことを確認します (ここに問題があります)。

[Test]
public void ValidDataShouldResultInNewRecordWithUsername()
{
    SignupService.CreateUser("myuser", "fakepassword");

    var q = from user in Context.Users 
            where user.Username == "myuser"
            select user;

    var actualUser = q.Single();

    Assert.AreEqual("myuser", actualUser.Username);
}

ここに私の質問があります:

1) まず第一に、これは EF に依存するサービスをテストする方法でもありますか? いくつかのアプローチがあることは知っていますが、このアプローチに異常がないことを確認したいだけです。

2) 2 番目に、データがコミットされる前に、サービス メソッド (CreateUser) が本来の動作を行ったことを確認するにはどうすればよいですか (コミットしたくないため、データベースの状態が初期化前の状態のままになるようにします)。各テスト)?上記のテストのクエリは、まだコミットされていないため、データを返しません。

4

2 に答える 2

6

#2 については、SQL Server を使用している場合は、スナップショットを使用できます。テスト データがロードされたら、スナップショットを作成します。次に、テストを実行し、ティアダウン (または使用するテスト後の方法) で、スナップショットに戻ります。スナップショットへの復帰は非常に高速であるため、DB をテストする実用的な方法です。

私がいくつかの成功に使用した別のアプローチがあります。SQL データベースを使用する代わりに、SQLCE データベースを使用します。次に、テスト データをファイルとして管理できます。とにかくデータベースを作成します。私はスナップショット アプローチの方が好きですが、どちらも機能します。

#1 の場合、これは統合テストです。アプリケーションのデータ部分をテストしているので、データベースにヒットすることはまさに正しいことです。リポジトリを抽象化すると、データベースに対してリポジトリをテストする必要があるため、複雑さが増すだけです。

がんばれ、エリック

于 2012-07-08T20:49:19.743 に答える
2

これは、私のすべての自動テストの状態に近いものです (単体テストも行っておらず、実際のデータベースに対する統合テストのみを行っています)。私が異なる方法で行っていることは主に 2 つあります。

1つ目は、セットアップでトランザクションスコープをセットアップし、コミットせずにティアダウンで破棄することです。これにより、更新されたデータを照会できます w ただし、次のテストのためにデータベースを元に戻すことができます。欠点は、ネストされたトランザクションがどのように機能するかがわからないため、おそらくサービスレイヤーでトランザクションスコープを使用できないことです。

私が行うもう 1 つのことは、EF 初期化クラスを呼び出して、起動時に完全なデータベースの再構築をトリガーすることです (ATM の前にコードがありません)。このようにして、テスト実行の開始時にシード データから新しいデータベースを取得することが保証されます。また、エンティティ構造が悪いかどうかを知らせてくれます。

于 2012-07-09T03:04:38.950 に答える