为什么实体框架中没有IDbContext
接口?如果现有的接口有类似SaveChanges()等的方法来测试,那么你可以从中导出自定义数据库上下文接口吗?
public interface ICustomDbContext : IDbContext
{
// add entity set properties to existing set of methods in IDbContext
IDbSet<SomeEntity> SomeEntities { get; }
}
我看到这个IDbContext
:
See this link然后你为你的Entities Context With That接口创建一个新的分部类。
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;
}
}
}
}
我也想到了这一点,我假设你将用它来嘲弄DbContext
。我没有理由这样做,除了你需要手动为你的模拟类手动实现你自己的DbSet
(所以无论如何都需要重写你自己的界面)。
只需创建一个模拟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)
{
}
}
}
没有IDbContext,因为它没用,它的唯一实现就是DbContext。
如果你看看这个design meeting note,EF团队也会用IDbSet这样做
对我来说,EF在单元测试方面的真正问题是DbContext中的DbConnection,幸运的是Effort是一个很好的项目,它开始填充这个问题。
Effort是一个功能强大的工具,可以方便地为基于Entity Framework的应用程序创建自动化测试。它基本上是一个ADO.NET提供程序,它在轻量级进程内主数据库而不是传统的外部数据库上执行所有数据操作。它提供了一些直观的帮助方法,使得这个提供程序与现有的ObjectContext或DbContext类一起使用变得非常容易。对现有代码的简单添加可能足以创建可在没有外部数据库的情况下运行的数据驱动测试。
有了这个,您可以保留DbContext和DbSet,并轻松进行单元测试。唯一的缺点是Linq提供商之间的差异,其中一些单元测试可能会通过努力而不是真正的后端。
使用EF7更新
我仍然认为IDbContext没用,问题来自DbConnection。
EF7也没有IDbContext,为了进行单元测试,他们现在提供内存提供程序。
你可以看到Rowan Miller在这里做一个演示:Modern Data Applications with Entity Framework 7