简体   繁体   English

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

[英]Unit testing Entity Framework 6 with context inheriting from IdentityDbContext

I'm looking to unit testing some methods using Entity Framework 6 using the instructions provided here . 我希望使用此处提供说明使用Entity Framework 6对某些方法进行单元测试。

My set-up is slightly different though - I'm also using ASP.Net Identity (the default implementation that uses EF). 我的设置略有不同 - 我也使用ASP.Net Identity(使用EF的默认实现)。 As such my context inherits from IdentityDbContext. 因此,我的上下文继承自IdentityDbContext。

When I run the tests I get an exception with the following details: 当我运行测试时,我得到一个例外,其中包含以下详细信息:

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.

I've read that in normal uses these are set up in the default OnModelCreating method. 我已经读过,在正常使用中,这些是在默认的OnModelCreating方法中设置的。

But can anyone offer advice on handling this within the mocked context illustrated in the method linked to above? 但是,有人可以提供有关在上面链接的方法中说明的模拟上下文中处理此问题的建议吗?

Thanks 谢谢

Andy 安迪

As pointed out in that article, when you mock out EF types you completely change their behaviour: the queries get executed as LINQ-to-Objects, not LINQ-to-SQL. 正如那篇文章所指出的那样,当你模拟EF类型时,你会完全改变它们的行为:查询将作为LINQ-to-Objects而不是LINQ-to-SQL执行。 This means you can easily write unit tests that pass for code that fails when it is used in the real world. 这意味着您可以轻松编写单元测试,以便在现实世界中使用时失败的代码。 A good example is: 一个很好的例子是:

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

That means you need to fully understand valid LINQ-to-SQL expressions to write the unit tests, but you were writing those unit tests because you wanted to validate your understanding. 这意味着您需要完全理解有效的LINQ-to-SQL表达式来编写单元测试,但是您正在编写这些单元测试,因为您想要验证您的理解。 So what has that really bought you? 那真的给你买了什么? How much value have you got from those unit tests? 你从这些单元测试中获得了多少价值? I'm saying this from the perspective of someone who once spent ages mocking out my EF layer only to find that once the database got involved the code was wrong. 我从一个曾经花了很多时间嘲笑我的EF层的人的角度来说这个,只是发现一旦数据库涉及到代码是错误的。

A better testing strategy in my opinion is to create Gateway classes that act as an intermediary between your DbContext and your consumers of that context. 在我看来,更好的测试策略是创建Gateway类,充当DbContext与该上下文的消费者之间的中介。

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

The Gateway s expose interfaces that can be effectively mocked. Gateway公开了可以有效模拟的接口。 Use those interfaces in your data consuming classes so that you can write high quality unit tests and then accept that you need to write integration tests to test the Gateway classes themselves: and those tests need a real database, so you need infrastructure for creating databases as part of your testing. 在数据消耗类中使用这些接口,以便您可以编写高质量的单元测试,然后接受您需要编写集成测试来自己测试Gateway类:这些测试需要一个真实的数据库,因此您需要用于创建数据库的基础结构部分测试。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM