web-dev-qa-db-ja.com

Entity Frameworkを使用するリポジトリパターンを単体テストするにはどうすればよいですか?

私は現在、EntityFrameworkを介して作成したリポジトリの単体テストを試みています。

私がしたいのは、実際のデータベースに実際に送信/接続せずにリポジトリをテストすることです。モックフレームワークを使用せずにこれを実行したいと思います。

現在、私のテストはデータベースにデータを送信しています。これはテスト専用であるため、実際のデータをデータベースに送信せずに、追加/削除などのメソッドをテストすることです。

リポジトリは次のとおりです。

namespace AbstractFactory.Repository
{
    using System.Collections.Generic;
    using System.Data.Entity;
    using System.Linq;

    /// <summary>
    /// This class serves as the structure of the Author repository using a database
    /// </summary>
    public class DbAuthorRepository : IRepository<AuthorEntity>
    {

        private AbstractFactoryPatternEntities context;

        public DbAuthorRepository(AbstractFactoryPatternEntities context)
        {
            this.context = context;
        }

        /// <summary>
        /// Adds the specified author.
        /// </summary>
        /// <param name="author">The author.</param>
        public void Add(AuthorEntity author)
        {
            context.AuthorEntities.Add(author);
        }

        /// <summary>
        /// Removes the specified author.
        /// </summary>
        /// <param name="author">The author.</param>
        public void Remove(AuthorEntity author)
        {
            this.context.AuthorEntities.Remove(author);
        }

        /// <summary>
        /// Saves this instance.
        /// </summary>
        public void Save()
        {
            this.context.SaveChanges();
        }

        /// <summary>
        /// Gets all.
        /// </summary>
        /// <returns>returns a list of all the authors</returns>
        public IEnumerable<AuthorEntity> GetAll()
        {
            List<AuthorEntity> result = this.context.AuthorEntities.Include(a => a.Books).ToList();

            return result;
        }

        /// <summary>
        /// Gets the author by id.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <returns>returns an entity</returns>
        public AuthorEntity GetById(int id)
        {
            AuthorEntity result = this.context.AuthorEntities.Single(a => a.AuthorId == id);

            return result;
        }
    }
}

単体テストの現在のコードは次のとおりです。

[TestMethod]
        public void Add_MethodIsCalled_EntityCountIsIncrementedByOne()
        {
            using (ShimsContext.Create())
            {
                ShimAbstractFactoryPatternEntities context = new ShimAbstractFactoryPatternEntities(new AbstractFactoryPatternEntities());
                DbAuthorRepository repository = new DbAuthorRepository(context);
                repository.Add(new AuthorEntity { FirstName = "Test", LastName = "testing=" });
                var actual = repository.GetAll().Count();
                repository.Save();
                var expected = repository.GetAll().Count();
                Assert.AreNotEqual(actual, expected);
            }

            //AbstractFactoryPatternEntities context = new AbstractFactoryPatternEntities();
            //DbAuthorRepository repository = new DbAuthorRepository(context);
            //var actual = repository.GetAll().Count();
            //repository.Add(new AuthorEntity { FirstName = "Testing", LastName = "MyTest" });
            //repository.Save();
            //var expected = repository.GetAll().Count();
            //Assert.AreNotEqual(actual, expected);
        }

        [TestMethod]
        public void Remove_MethodIsCalled_EntityCountRemainsTheSame()
        {
            AbstractFactoryPatternEntities context = new AbstractFactoryPatternEntities();
            DbAuthorRepository repository = new DbAuthorRepository(context);
            AuthorEntity newAuthor = new AuthorEntity { FirstName = "Testing", LastName = "MyTest" };
            repository.Add(newAuthor);
            repository.Save();
            var actual = repository.GetAll().Count();
            Console.WriteLine(actual);
            repository.Remove(newAuthor);
            var expected = repository.GetAll().Count();
            Console.WriteLine(expected);
            Assert.AreEqual(actual, expected);
        }

        [TestMethod]
        public void Get_MethodIsCalled_CorrectAuthorIsRetrieved()
        {
            AbstractFactoryPatternEntities context = new AbstractFactoryPatternEntities();
            DbAuthorRepository repository = new DbAuthorRepository(context);
            int target = 4;
            AuthorEntity author = repository.GetById(target);
            Assert.AreEqual(target, author.AuthorId);
        }

テストを行うためにシム/スタブ/フェイクを使用したいと思います。

16
Randel Ramirez

Entity Frameworkリポジトリは、リポジトリインターフェイスの具体的な実装です。具体的であるため、データベースなしで抽象化してテストすることはできません。この具体的な実装の要点は、データベースにデータを書き込むことです。

つまり、EFリポジトリのテストは、リポジトリが実際のデータベースに書き込むことを確認することを目的とする必要があります。テストの実行フェーズではリポジトリメソッドを呼び出し、アサートフェーズではデータベース(ado.net)からデータを取得する他の方法を使用します。おそらく?)リポジトリがその仕事をしているかどうかを確認します。

さらに別の無関係なことは、インメモリデータストアを使用するリポジトリの別の実装を作成でき、そのようなインメモリリポジトリを他のサービスに挿入すると、物理データベースに書き込むことなくこれらのサービスをテストできることです。動作テストを実行するためだけに、他のサービスに挿入されたリポジトリをモックすることもできます。つまり、サービスがリポジトリを正しく使用しているかどうかをテストします。

17
Wiktor Zychla

データベースへの接続を、EffortなどのインメモリDBに置き換えることができます。次に、リポジトリロジックをテストできます。詳細はこちらをご覧ください こちら

7
druss