简体   繁体   English

如何对使用Entity Framework的存储库模式进行单元测试?

[英]How to unit test a repository pattern that uses Entity Framework?

I'm currently trying to unit test a repository I made through Entity Framework: 我目前正在尝试对通过Entity Framework进行的存储库进行单元测试:

What I want to happen is that test the repository without actually sending/connecting to the actual database, I want to this without using any mocking framework. 我想要发生的是测试存储库而不实际发送/连接到实际的数据库,我想这样做而不使用任何模拟框架。

Currently my test is sending the data to the database, what I want to happen is test the add/remove etc. methods without sending the actual data to the database since it's only for testing. 目前我的测试是将数据发送到数据库,我想要发生的是测试添加/删除等方法而不将实际数据发送到数据库,因为它仅用于测试。

Here is the repository: 这是存储库:

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

Here is the current code for the unit test: 以下是单元测试的当前代码:

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

I want to use shims/stub/fakes in order to make the test. 我想使用shims / stub / fakes来进行测试。

The Entity Framework repository is a concrete implementation of your repository interface. 实体框架存储库是存储库接口的具体实现。 Because it is concrete, you can't abstract it and test without the database - the whole point of this concrete implementation is to write the data to the database! 因为它是具体的,你不能抽象它并在没有数据库的情况下进行测试 - 这个具体实现的重点是将数据写入数据库!

This means that testing EF repositories should rather aim at verifying that repositories write to actual database - in the act phase of your test you invoke repository methods and in the assert phase you use any other way of getting the data from the database (ado.net perhaps?) to check if the repository does its job. 这意味着测试EF存储库的目的应该是验证存储库是否写入实际数据库 - 在测试的行为阶段调用存储库方法,在断言阶段,您可以使用任何其他方式从数据库获取数据(ado.net)或许?)检查存储库是否完成了它的工作。

Yet another, unrelated thing is that you can have another implementation of the repository which uses an in-memory data store and injecting such in-memory repository to other services allows you to test these services wihout writing to a physical database. 另一个不相关的事情是,您可以使用内存数据存储的另一个存储库实现,并将这样的内存存储库注入其他服务,允许您在不写入物理数据库的情况下测试这些服务。 You could even mock a repository injected to other services just to perform some behavioral tests, ie test whether your services use your repositories correctly. 您甚至可以模拟注入其他服务的存储库,只是为了执行一些行为测试,即测试您的服务是否正确使用您的存储库。

You can replace connection to your database with in-memory DB, such as Effort. 您可以使用内存数据库(例如Effort)替换与数据库的连接。 Then you can test your repository logic. 然后,您可以测试您的存储库逻辑。 In more details can be found here 更多细节可以在这里找到

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用Lambda表达式进行单元测试实体框架/存储库模式 - How to unit test with lambda expressions Entity Framework/Repository pattern 如何对使用Entity Framework创建对象的存储库层方法进行单元测试? - How to unit test a repository layer method that uses Entity Framework to create objects? 如何正确地对与Entity Framework / DbContext耦合的存储库模式方法进行单元测试? - How do I properly unit test a repository-pattern method, that has coupling to Entity Framework / DbContext? 使用带有接口的存储库模式时,如何使用实体框架和 Moq 进行单元测试? - How I unit test with Entity Framework and Moq when using a repository pattern with Interface? 实体框架,存储库模式,工作单元和测试 - Entity Framework, Repository Pattern, Unit of Work and Testing 我应该如何对使用Entity Framework实现的存储库方法进行单元测试? - How should I unit test a repository method implemented with Entity Framework? 如何使用ADO.NET实体框架测试存储库模式? - How to test Repository Pattern with ADO.NET Entity Framework? 如何单元测试实体框架? - How to unit test Entity Framework? 使用Unity for Work of Unit / Repository模式创建Entity Framework对象 - Creating Entity Framework objects with Unity for Unit of Work/Repository pattern 使用Entity Framework 5和存储库模式和工作单元过滤内部集合 - Filtering inner collection with Entity Framework 5 and Repository pattern and Unit of Work
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM