我希望使用 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 方法中设置的。
但是任何人都可以提供有关在上面链接的方法中说明的模拟上下文中处理此问题的建议吗?
谢谢
安迪
最佳答案
正如该文章中所指出的,当您模拟 EF 类型时,您将完全改变它们的行为:查询将作为 LINQ-to-Objects 而不是 LINQ-to-SQL 执行。这意味着您可以轻松地为在现实世界中使用时失败的代码编写单元测试。一个很好的例子是:
context.Foos.Where(candidate => SomePredicate(candidate));
这意味着您需要完全理解有效的 LINQ-to-SQL 表达式才能编写单元测试,但您编写这些单元测试是因为您想验证您的理解。那到底给你带来了什么?您从这些单元测试中获得了多少值(value)?我是从一个曾经花了很长时间模拟我的 EF 层的人的角度说的,结果发现一旦涉及到数据库,代码就错了。
在我看来,更好的测试策略是创建 Gateway
类,充当 DbContext
和该上下文的使用者之间的中介。
class FooGateway : IFooGateway
{
IEnumerable<Foo> GetFoosThatObeySomePredicate() { /* ... */ }
}
Gateway
公开了可以有效模拟的接口(interface)。在您的数据消费类中使用这些接口(interface),以便您可以编写高质量的单元测试,然后接受您需要编写集成测试以测试 Gateway
类本身:以及那些测试需要一个真实的数据库,因此您需要在测试过程中创建数据库的基础设施。
关于c# - 使用继承自 IdentityDbContext 的上下文对 Entity Framework 6 进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23184969/