单元测试实体框架6,其上下文继承自IdentityDbContext

本文关键字:上下文 继承 IdentityDbContext 实体 框架 单元测试 | 更新日期: 2023-09-27 17:59:03

我希望使用这里提供的说明,使用Entity Framework 6对一些方法进行单元测试。

不过,我的设置略有不同——我也在使用ASP。Net Identity(使用EF的默认实现)。因此,我的上下文继承自IdentityDbContext。

当我运行测试时,我得到了一个异常,其中包含以下详细信息:

Castle.Proxies.IdentityUserLogin: : EntityType 'IdentityUserLogin' has no key defined. Define the key for this EntityType.    
Castle.Proxies.IdentityUserRole: : EntityType 'IdentityUserRole' has no key defined. Define the key for this EntityType.    
IdentityUserLogins: EntityType: EntitySet 'IdentityUserLogins' is based on type 'IdentityUserLogin' that has no keys defined.    
IdentityUserRoles: EntityType: EntitySet 'IdentityUserRoles' is based on type 'IdentityUserRole' that has no keys defined.

我读到,在正常使用中,这些都是在默认的OnModelCreating方法中设置的。

但是,有人能在上面链接的方法中所示的模拟上下文中提供处理这一问题的建议吗?

感谢

Andy

单元测试实体框架6,其上下文继承自IdentityDbContext

正如那篇文章中所指出的,当您模拟EF类型时,您完全改变了它们的行为:查询将作为LINQ to Objects而不是LINQ to SQL执行。这意味着您可以轻松地编写单元测试,以通过在现实世界中使用时失败的代码。一个很好的例子是:

context.Foos.Where(candidate => SomePredicate(candidate));

这意味着您需要完全理解有效的LINQ到SQL表达式才能编写单元测试,但编写这些单元测试是因为您想验证您的理解。那你到底买了什么?你从这些单元测试中得到了多少价值?我是从一个曾经花了很长时间嘲笑我的EF层,却发现一旦数据库参与进来,代码就错了的人的角度说这句话的。

在我看来,更好的测试策略是创建Gateway类,作为DbContext和该上下文的消费者之间的中介。

class FooGateway : IFooGateway
{
    IEnumerable<Foo> GetFoosThatObeySomePredicate() { /* ... */ }
}

Gateway公开了可以有效模拟的接口。在数据消耗类中使用这些接口,这样您就可以编写高质量的单元测试,然后接受需要编写集成测试来测试Gateway类本身:这些测试需要一个真实的数据库,因此您需要用于创建数据库的基础设施作为测试的一部分。