我在 MVC 5、Entity Framework 6 应用程序中成功地使用 Moq 模拟对我的 BusAct 控制器进行了集成测试,该应用程序基于一个简单的成员资格数据库。但现在我已将数据库迁移到 Identity 2.0 并将 UserProfile 替换为 ApplicationUser。
IdentityDbContext:(修改自简单成员 DbContext)
public class MyDb : IdentityDbContext<ApplicationUser> // DbContext
{
public MyDb () : base("MyApplication") { }
// public virtual DbSet<UserProfile> UserProfiles { get; set; }
public virtual DbSet<BusAcnt> BusAcnts { get; set; } // marking as virtual allows mocking override
public virtual DbSet<...>
...
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
模拟数据库设置:
public class MockDbSetup
{
public static Mock<MyDb> MockMyDb()
{
var dataBa = new List<BusAcnt> {
new BusAcnt {Id = 0, CmpnyName = "Company 1", NmOfc = 1, Status = "Active"},
new BusAcnt {Id = 1, CmpnyName = "Company 2", NmOfc = 1, Status = "Active"},
new BusAcnt {Id = 2, CmpnyName = "Company 3", NmOfc = 1, Status = "Active"},
new BusAcnt {Id = 3, CmpnyName = "Company 4", NmOfc = 1, Status = "Active"},
new BusAcnt {Id = 4, CmpnyName = "Company 5", NmOfc = 1, Status = "Active"},
new BusAcnt {Id = 5, CmpnyName = "Company 6", NmOfc = 1, Status = "Active"}
}.AsQueryable();
var mockSetBa = new Mock<DbSet<BusAcnt>>();
mockSetBa.As<IQueryable<BusAcnt>>().Setup(m => m.Provider).Returns(dataBa.Provider);
mockSetBa.As<IQueryable<BusAcnt>>().Setup(m => m.Expression).Returns(dataBa.Expression);
mockSetBa.As<IQueryable<BusAcnt>>().Setup(m => m.ElementType).Returns(dataBa.ElementType);
mockSetBa.As<IQueryable<BusAcnt>>().Setup(m => m.GetEnumerator()).Returns(dataBa.GetEnumerator());
var MyDb = new Mock<MyDb>();
mockMyDb.Setup(c => c.BusAcnts).Returns(mockSetBa.Object);
return mockMyDb;
}
}
集成测试:
[Fact]
public void GetAllBusAcnt()
{
var mockMyDb = MockDBSetup.MockMyDb();
var controller = new BusAcntController(mockMyDb.Object);
var controllerContextMock = new Mock<ControllerContext>();
controllerContextMock.Setup(
x => x.HttpContext.User.IsInRole(It.Is<string>(s => s.Equals("admin")))
).Returns(true);
controller.ControllerContext = controllerContextMock.Object;
var viewResult = controller.Index() as ViewResult;
var model = viewResult.Model as PagedBusIdxModel;
Assert.NotNull(model);
Assert.Equal(6, model.BusAcnts.ToList().Count());
Assert.Equal("Company 2", model.BusAcnts.ToList()[1].CmpnyName);
}
当我现在运行测试时,出现以下错误:
System.Data.Entity.ModelConfiguration.ModelValidationExceptionOne or more validation errors were detected during model generation:
Castle.Proxies.IdentityUserRole: : EntityType 'IdentityUserRole' has no key defined. Define the key for this EntityType.
Castle.Proxies.IdentityUserLogin: : EntityType 'IdentityUserLogin' has no key defined. Define the key for this EntityType.
IdentityUserRoles: EntityType: EntitySet 'IdentityUserRoles' is based on type 'IdentityUserRole' that has no keys defined.
IdentityUserLogins: EntityType: EntitySet 'IdentityUserLogins' is based on type 'IdentityUserLogin' that has no keys defined.
at System.Data.Entity.Core.Metadata.Edm.EdmModel.Validate()
at System.Data.Entity.DbModelBuilder.Build(DbProviderManifest providerManifest, DbProviderInfo providerInfo)
at System.Data.Entity.DbModelBuilder.Build(DbConnection providerConnection)
at System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext)
at System.Data.Entity.Internal.RetryLazy`2.GetValue(TInput input)
at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
at System.Data.Entity.Internal.InternalContext.CreateObjectContextForDdlOps()
at System.Data.Entity.Database.Exists()
at Microsoft.AspNet.Identity.EntityFramework.IdentityDbContext`1.IsIdentityV1Schema(DbContext db)
at Microsoft.AspNet.Identity.EntityFramework.IdentityDbContext`1..ctor(String nameOrConnectionString, Boolean throwIfV1Schema)
at Microsoft.AspNet.Identity.EntityFramework.IdentityDbContext`1..ctor(String nameOrConnectionString)
at MyApplication.Models.MyDb..ctor() in MyDb.cs: line 9
at Castle.Proxies.MyDbProxy..ctor(IInterceptor[])
我相信我需要修改 MockDbSetup 但无法找到有关如何执行此操作的任何信息。
我尝试添加
var dataUsr = new List<ApplicationUser>
{
new ApplicationUser { UserName = "Test", PasswordHash = "a123cdefg"} }.AsQueryable();
var mockSetUsr = new Mock<DbSet<ApplicationUser>>();
mockSetUsr.As<IQueryable<BusAcnt>>().Setup(m => m.Provider).Returns(dataUsr.Provider);
mockSetUsr.As<IQueryable<BusAcnt>>().Setup(m => m.Expression).Returns(dataUsr.Expression);
mockSetUsr.As<IQueryable<BusAcnt>>().Setup(m => m.ElementType).Returns(dataUsr.ElementType);
mockSetUsr.As<IQueryable<BusAcnt>>().Setup(m => m.GetEnumerator()).Returns(dataUsr.GetEnumerator());
但我收到“无法解决”错误GetEnumerator
也没有
mockMyDb.Setup(c => c.AspNetUsers).Returns(mockSetUsr.Object);
或者
mockMyDb.Setup(c => c.ApplicationUser).Returns(mockSetUsr.Object);
有效,因为它无法解决AspNetUsers
or ApplicationUser
。
有没有人知道如何做到这一点,关于模拟 Identity 2.0 数据库的文档的链接会特别有用吗?