58

IDbContext为什么实体框架中没有接口?如果有一个现有接口,其中包含 SaveChanges() 等方法,您可以从中派生您的自定义数据库上下文接口,那么测试事情不是更容易吗?

public interface ICustomDbContext : IDbContext
{
    // add entity set properties to existing set of methods in IDbContext
    IDbSet<SomeEntity> SomeEntities { get; }
}
4

4 回答 4

16

我看到这个IDbContext

请参阅此链接然后您使用该接口为您的实体上下文创建一个新的部分类。

public partial class YourModelEntities : DbContext, IDbContext 

编辑:我编辑了这篇文章,这对我有用。我的背景

namespace dao
{
    public interface ContextI : IDisposable
    {
        DbSet<TEntity> Set<TEntity>() where TEntity : class;
        DbSet Set(Type entityType);
        int SaveChanges();
        IEnumerable<DbEntityValidationResult> GetValidationErrors();
        DbEntityEntry<TEntity> Entry<TEntity>(TEntity entity) where TEntity:class;
        DbEntityEntry Entry(object entity);
        string ConnectionString { get; set; }
        bool AutoDetectChangedEnabled { get; set; }
        void ExecuteSqlCommand(string p, params object[] o);
        void ExecuteSqlCommand(string p);
    }
}

YourModelEntities 是你自动生成的分部类,你需要创建一个新的同名分部类,然后添加你的新上下文接口,这个例子是 ContextI

注意:该接口并未实现所有方法,因为这些方法是在您的自动生成代码中实现的。

namespace dao
{
    public partial class YourModelEntities :DbContext, ContextI
    {
        public string ConnectionString
        {
            get
            {
                return this.Database.Connection.ConnectionString;
            }
            set
            {
                this.Database.Connection.ConnectionString = value;
            }
        }

        bool AutoDetectChangedEnabled
        {
            get
            {
                return true;
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public void ExecuteSqlCommand(string p,params object[] os)
        {
            this.Database.ExecuteSqlCommand(p, os);
        }

        public void ExecuteSqlCommand(string p)
        {
            this.Database.ExecuteSqlCommand(p);
        }

        bool ContextI.AutoDetectChangedEnabled
        {
            get
            {
                return this.Configuration.AutoDetectChangesEnabled;
            }
            set
            {
                this.Configuration.AutoDetectChangesEnabled = value;
            }
        }
      
    }
}
于 2013-11-26T21:49:51.093 回答
0

只需创建一个模拟 DbContext 扩展您的生产 DbContext 覆盖使测试复杂化的方法。这样,对生产 DbContext 的任何更改都会自动反映在测试中,除了覆盖的方法。对于任何其他处理持久性并采用 DbContext 的类,只需扩展它们以及传入扩展的模拟 DbContext。

namespace Test.Mocks
{  
    public sealed class MockDatabaseContext : MainProject.Persistence.Database.DatabaseContext
    {
        public MockDatabaseContext(ConfigurationWrapper config) : base(config)
        {

        }      
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {

            var dbPath = "test.db";
            optionsBuilder.UseSqlite($"Filename={dbPath}");


        }
    }
}

namespace Test.Mocks
{

    public class MockInventoryFacade : InventoryFacade
    {        
        public MockInventoryFacade(MockDatabaseContext databaseContext) : base(databaseContext)
        {

        }    
    }
}
于 2017-12-27T03:41:15.237 回答
0

我也在考虑这个问题,我假设你会用它来模拟 DbContext。我找不到这样做的理由,除了你需要DbSet在你的模拟类中手动实现你自己的(所以无论如何都需要重写你自己的接口)。

于 2017-11-22T01:52:07.567 回答
-13

没有 IDbContext,因为它没有用,唯一的实现是 DbContext。

如果您查看此设计会议记录,EF 团队也将采用 IDbSet 的方式

对我来说,EF 在单元测试方面的真正问题是 DbContext 中的 DbConnection,幸运的是,Effort是 codeplex 上的一个不错的项目,它开始填补这个问题。

Effort 是一个强大的工具,可以方便地为基于实体框架的应用程序创建自动化测试。它基本上是一个 ADO.NET 提供程序,它在轻量级进程内主内存数据库而不是传统的外部数据库上执行所有数据操作。它还提供了一些直观的帮助器方法,可以很容易地将此​​提供程序与现有的 ObjectContext 或 DbContext 类一起使用。对现有代码的简单添加可能足以创建可以在没有外部数据库存在的情况下运行的数据驱动测试。

有了这个,你可以让你的 DbContext 和 DbSet 保持原样并轻松地进行单元测试。唯一的缺点是 Linq 提供者之间的差异,其中一些单元测试可能通过努力而不是真正的后端。

使用 EF7 更新

我仍然认为 IDbContext 没有用,问题来自 DbConnection。

EF7 也没有 IDbContext,为了进行单元测试,他们现在提供了一个内存提供程序。

你可以在这里看到 Rowan Miller 做一个演示:Modern Data Applications with Entity Framework 7

于 2013-09-11T22:39:39.053 回答