我偶然发现了下一个问题......我有数据库上下文:
// For support unit testing...
public interface IDbContext : IDisposable
{
IQueryable<Hardware> Hardwares { get; }
IQueryable<ProviderHardware> ProviderHardwares { get; }
}
// Real DbContext (EF 4.0, Code First)
public class PrimaryDbContext : DbContext, IDbContext
{
public DbSet<Hardware> Hardwares { get; set; }
public DbSet<ProviderHardware> ProviderHardwares { get; set; }
IQueryable<Hardware> IDbContext.Hardwares
{ get { return Hardwares; } }
IQueryable<ProviderHardware> IDbContext.ProviderHardwares
{ get { return ProviderHardwares; } }
...
}
我尝试获取所有硬件,这些硬件在ProviderHardwares表中不存在:
var hardwaresRemoved = db.Hardwares.Where(i => (i.IsAvailable == true) &&
(db.ProviderHardwares.Count(j => j.Article == i.Article) == 0)).ToList();
如果我严格使用PrimaryDbContext,例如“PrimaryDbContext db = new PrimaryDbContext();”一切正常。但如果我隐式使用它“IDbContext db = new PrimaryDbContext();”我得到一个例外:
无法创建类型的常量值 'ConfiguratorMvcApplication.DomainModels.ProviderHardware'。只要 支持原始类型(例如Int32,String和Guid') 这个背景。
总结一下,我无法替换IQueryable上的DbSet。在这种情况下我如何使用单元测试?我希望有人已经解决了这个问题...... 非常感谢!
答案 0 :(得分:1)
我最终为每个DbSet提供了两个属性:一个是IQueryable类型,另一个是DbSet类型。 IQueryable属性在接口中定义,它将调用中继到具体实现(类型为DbSet的属性),如下所示:
// Exists in the interface
public IQueryable<AccountContact> AccountContacts
{
get
{
return DbAccountContacts;
}
set
{
DbAccountContacts = (DbSet<AccountContact>)value;
}
}
// Exists only in the implementation
public DbSet<AccountContact> DbAccountContacts { get; set; }
通过这种设置,我能够使模拟正常工作,并可以对代码进行单元测试。
对于OP来说,这肯定为时已晚,但也许这会帮助那些正在努力解决同一问题的人,就像我一样。
答案 1 :(得分:-2)
我建议您最好保留DbSets并执行集成测试 ,包括 数据库。
因为虽然通过使用数据库模拟进行单元测试可能会有所帮助,但您最好不要使用真实数据库进行测试(但它不是单元测试)。
在ClassInitialize上擦除数据库和/或创建初始数据以进行测试。
如果使用连接字符串创建App.config文件,则可以拥有单独的测试数据库,如果使用的是EF Code First,则可以免费获得。
最好的问候。