Moq Mocking with Identity 2.0数据库 [英] Moq Mocking with Identity 2.0 Database

查看:302
本文介绍了Moq Mocking with Identity 2.0数据库的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在基于简单会员数据库的MVC 5,实体框架6应用程序中,使用Moq对我的BusAct控制器进行了嘲笑,成功建立了集成测试。但是现在我已将数据库迁移到Identity 2.0,并用ApplicationUser替换UserProfile。



IdentityDbContext :(从简单成员DbContext修改)

  public class MyDb:IdentityDbContext< ApplicationUser> // DbContext 
{
public MyDb():base(MyApplication){}

// public virtual DbSet< UserProfile> UserProfiles {get;组; }
public virtual DbSet& BusAcnt> BusAcnts {get;组; } //标记为虚拟允许嘲笑覆盖
public virtual DbSet< ...>
...

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove< PluralizingTableNameConvention>();
}
}

MockDbSetup:

  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},
新的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())返回(dataBa.GetEnumerator());
var MyDb = new Mock< MyDb>();
mockMyDb.Setup(c => c.BusAcnts).Returns(mockSetBa.Object);
return mockMyDb;
}
}

集成测试:

  [事实] 
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)))
)。返回(真);
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.ModelValidationException在模型生成期间检测到一个或多个验证错误:

Castle.Proxies。 IdentityUserRole::EntityType'IdentityUserRole'没有定义键。定义此EntityType的键。
Castle.Proxies.IdentityUserLogin::EntityType'IdentityUserLogin'没有定义键。定义此EntityType的键。
IdentityUserRoles:EntityType:EntitySet'IdentityUserRoles'基于没有定义键的类型'IdentityUserRole'。
IdentityUserLogins:EntityType:EntitySet'IdentityUserLogins'基于没有定义键的IdentityUserLogin类型。 System.Data.Entity.Core.Metadata.Edm.EdmModel.Validate()
在System.Data.Entity.DbModelBuilder.Build(DbProviderManifest providerManifest,DbProviderInfo providerInfo)
在System。 Data.Entity.DbModelBuilder.Build(DbConnection providerConnection)
在System.Data.Entity.Internal.LazyInternalContext.CreateModel(LazyInternalContext internalContext)
在System.Data.Entity.Internal.RetryLazy`2.GetValue( TInput输入)
在System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
在System.Data.Entity.Internal.InternalContext.CreateObjectContextForDdlOps()
在System.Data.Entity。 Database.Exists()
在Microsoft.AspNet.Identity.EntityFramework.IdentityDbContext`1.IsIdentityV1Schema(DbContext db)
在Microsoft.AspNet.Identity.EntityFramework.IdentityDbContext`1..ctor(String nameOrConnectionString, Boolean throwIfV1Schema)
在Microsoft.AspNet.Identity.EntityFramework.IdentityDbContext`1..ctor(String在MyDb.cs中的MyApplication.Models.MyDb..ctor()中的
$ 9
在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

code>



而且

  mockMyDb.Setup c => c.AspNetUsers).Returns(mockSetUsr.Object); 

  mockMyDb.Setup(c => c.ApplicationUser).Returns(mockSetUsr.Object); 

因为无法解析 AspNetUsers 或有没有人想知道如何做到这一点,链接到嘲弄一个Identity 2.0数据库的文档。 ApplicationUser



<会特别有帮助吗?

解决方案

谢谢Jamie,反过来Andreas在测试框架说实体没有为内置实体定义关键字。



MockDbSetup 中的 MockMyDb() {CallBase = true}; to var MyDb = new Mock< MyDb>(); 导致

  var MyDb = new Mock< MyDb>(){CallBase = true}; 


I successfully set up an Integration Test using mocking with Moq against my BusAct controller in an MVC 5, Entity Framework 6 app based on a Simple membership database. But now I have migrated the database to Identity 2.0 and replaced the UserProfile with ApplicationUser.

IdentityDbContext: (Modified from Simple membership 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>();
    }
  }

MockDbSetup:

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

Integration Test:

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

When I run the test now I get these errors:

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[])

I believe I need to modify the MockDbSetup but have not been able to find any information on how to do that.

I tried adding

  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()); 

But I get a "Can't resolve" error on GetEnumerator

And neither

  mockMyDb.Setup(c => c.AspNetUsers).Returns(mockSetUsr.Object);  

or

  mockMyDb.Setup(c => c.ApplicationUser).Returns(mockSetUsr.Object);

works because it cannot resolve either AspNetUsers or ApplicationUser.

Does anyone have an idea of how to do this, links to documentation on mocking an Identity 2.0 database would be especially helpful?

解决方案

Thank you to Jamie and in turn Andreas' answer at Testing framework says entity has no key defined for built in entity.

In the MockMyDb() method in MockDbSetup add { CallBase = true }; to var MyDb = new Mock<MyDb>(); resulting in

var MyDb = new Mock<MyDb>() { CallBase = true };

这篇关于Moq Mocking with Identity 2.0数据库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆