使用从IdentityDbContext继承的上下文对Entity Framework 6进行单元测试

时间:2014-04-20 16:43:15

标签: c# asp.net entity-framework unit-testing asp.net-identity

我希望使用instructions provided here使用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方法中设置的。

但是,有人可以提供有关在上面链接的方法中说明的模拟上下文中处理此问题的建议吗?

由于

安迪

1 个答案:

答案 0 :(得分:0)

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

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

这意味着您需要完全理解有效的LINQ-to-SQL表达式来编写单元测试,但是您正在编写这些单元测试,因为您想要验证您的理解。那真的给你买了什么?你从这些单元测试中获得了多少价值?我是从一个曾经花了很多时间嘲笑我的EF层的人的角度来说这个,只是发现一旦数据库涉及到代码是错误的。

我认为更好的测试策略是创建Gateway个类,充当您的DbContext和该上下文的消费者之间的中介。

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

Gateway公开可以有效模拟的接口。在数据消耗类中使用这些接口,以便您可以编写高质量的单元测试,然后接受需要编写集成测试来自己测试Gateway类:这些测试需要一个真正的数据库,因此您需要基础架构来创建数据库作为测试的一部分。