我如何单元测试实体框架代码优先映射?

STW*_*STW 12 c# unit-testing ef-code-first entity-framework-4.3

我正在使用Code First将类映射到现有数据库.我需要一种方法来对这些映射进行单元测试,这些映射是基于约定,基于属性和流畅的api的混合.

要进行单元测试,我需要确认类的属性映射到数据库中正确的表名和列名.此测试需要针对上下文执行,并且应首先涵盖代码的所有配置选项.

在非常高的层次上,我想要断言像(伪代码):

Assert.IsTrue(context.TableFor<Widget>().IsNamed("tbl_Widget"));
Assert.IsTrue(context.ColumnFor<Widget>(w => w.Property).IsNamed("WidgetProperty"));
Run Code Online (Sandbox Code Playgroud)

Sea*_*ean 0

我能想到的覆盖所有可能选项的唯一方法是使用 Entity Framework Power Tools 预编译 DbContext 的视图,并且可能结合使用生成类型的反射和生成代码本身的 RegEx 来验证所有内容都按照您想要的方式映射。对我来说听起来很痛苦。

我想到的另一件事是在 DbModelBuilder 周围创建一个外观来拦截和检查通过它的所有内容,但我不知道这是否可以处理基于约定的内容。听起来也很痛苦。

作为一种不太完整但更简单的替代方案,您可以通过尽可能切换到基于属性的映射来消除其中的很大一部分。这将允许您创建一个基测试类,例如 ModelTesting<TEntity>,其中包括一些使用反射来验证 TEntity 是否具有的测试方法:

  • 单个 TableAttribute。
  • 每个属性都有一个 ColumnAttribute 或 NotMappedAttribute。
  • 至少一个具有 KeyAttribute 的属性。
  • 每个属性类型都映射到兼容的数据库类型。

您甚至可以根据属性和类的名称强制执行命名约定(对每个层次结构表类型有一个警告)。还可以检查外键映射。这是一个一次性编写的基类,您可以为每种模型类型派生一次并捕获大部分错误(好吧,无论如何,它捕获了我的大部分错误)。

任何不能用属性表示的东西,比如 TPH 继承等,都会变得有点困难。假设您的 DbContext 没有为您生成数据库,那么启动 DbContext 并在 Set<TEntity>() 上执行 FirstOrDefault 的集成测试可能会涵盖大部分基础知识。