【问题标题】:NUnit -> Moq (Mock) DbSet and DbContext -> EntityType 'ApplicationUserLogin' has no key defined. -> ChangeTracker.Entries()NUnit -> Moq (Mock) DbSet 和 DbContext -> EntityType 'ApplicationUserLogin' 没有定义键。 -> ChangeTracker.Entries()
【发布时间】:2018-01-22 15:06:56
【问题描述】:

运行我的测试我得到以下错误:

System.Data.Entity.ModelConfiguration.ModelValidationException:一 在模型生成期间检测到或更多验证错误:

Castle.Proxies.ApplicationUserLogin: : EntityType 'ApplicationUserLogin' 没有定义键。为此定义密钥 实体类型。 Castle.Proxies.ApplicationUserRole: : EntityType 'ApplicationUserRole' 没有定义键。为此定义密钥 实体类型。应用程序用户登录:实体类型:实体集 'ApplicationUserLogins' 基于类型 'ApplicationUserLogin' 没有定义键。应用程序用户角色:实体类型:实体集 'ApplicationUserRoles' 基于类型 'ApplicationUserRole' 没有定义键。

我发现测试在覆盖SaveChanges 时失败,特别是ChangeTracker.Entries()

我发现以下线程建议调用 OnModelCreating 可以解决问题,但这对我不起作用。

https://*.com/a/34786782/3850405

该错误仅在我测试代码时发生,从控制器运行它可以正常工作。

测试来源:

https://msdn.microsoft.com/en-us/library/dn314429(v=vs.113).aspx#code-snippet-4

NUnit 测试:

[Test]
public void CreateCustomerNumber_saves_a_CustomerNumber_via_context()
{
    var mockSet = new Mock<DbSet<CustomerNumber>>();

    var mockContext = new Mock<ApplicationDbContext>();
    //mockContext.Object.TestModelCreation(new DbModelBuilder());
    mockContext.Setup(c => c.CustomerNumbers).Returns(mockSet.Object);

    var service = new CustomerNumberService(mockContext.Object);

    service.Add(new CustomerNumberViewModel(){CustomerNumber = "AAA"});

    mockSet.Verify(m => m.Add(It.IsAny<CustomerNumber>()), Times.Once());
    mockContext.Verify(m => m.SaveChanges(), Times.Once());
}

服务,直接调用就可以了:

public void Add(CustomerNumberViewModel model)
{
    var customerNumber = new CustomerNumber()
    {
        CustomerNumber = model.CustomerNumber,
    };

    db.CustomerNumbers.Add(customerNumber);
    //SaveChanges fails 
    db.SaveChanges();
}   

ApplicationDbContext:

//If the override is removed, everything works
public sealed override int SaveChanges()
{
    OnBeforeSave();
    return base.SaveChanges();
}

//Did not make any difference 
//public void TestModelCreation(DbModelBuilder model)
//{
//    OnModelCreating(model);
//}


protected void OnBeforeSave()
{
    var now = DateTime.Now;

    //This line causes the exception
    foreach (var changedEntity in ChangeTracker.Entries())
    {
        var entity = changedEntity.Entity as IEntity;
        if (entity != null)
        {
            switch (changedEntity.State)
            {
                case EntityState.Added:
                    entity.Created = now;
                    entity.Updated = now;
                    break;

                case EntityState.Modified:
                    Entry(entity).Property(x => x.Created).IsModified = false;
                    entity.Updated = now;
                    break;
            }
        }
    }
}

【问题讨论】:

  • 如果您投反对票,请说明原因。

标签: c# entity-framework unit-testing nunit moq


【解决方案1】:

问题在于 SaveChangessealed 修饰符。切换到public override int SaveChanges(),一切正常。

【讨论】: