【发布时间】:2021-06-28 17:53:04
【问题描述】:
我正在尝试为实体框架项目中的数据库构建集成测试模式,但在寻找接缝时遇到了一些挑战。假设我有一个模型,它可能具有复杂的属性...
public class Sample {
public string Name { get; set; }
/* many other complex / required properties */
}
我的典型测试模式会遵循 AAA:
public void Test() {
// Arrange
var sample1 = new Sample() { Name = "Test1", /* ... */ };
var sample2 = new Sample() { Name = "Test2", /* ... */ };
_context.Set<Sample>().AddRange(sample1, sample2);
_context.SubmitChanges();
// Act
var results = _systemUnderTest.Act();
// Assert
Assert.IsNotNull(results)
}
由于实体对象非常复杂,配置所有实体所需的字段是一项艰巨的任务。通常,所有这些字段都不需要是测试的特定值。所以我想采用一种使用派生类和构造函数的模式,这样我就可以使用对象初始化器并删除很多样板。
public class SampleTest() : Sample {
public SampleTest() {
Name = "Test";
/* other default values and complex initialization */
}
}
public void Test() {
var sample1 = new TestSample();
var sample2 = new TestSample { Name = "Custom Name for Test" };
_context.Set<Sample>().AddRange(sample1, sample2);
_context.SaveChanges();
/* snip */
}
但是,当我这样做时,我收到错误'Mapping and metadata information could not be found for EntityType 'TestSample'. 我理解错误消息,但我希望有一种方法可以选择退出或绕过它。我想确定一个接缝,我可以指示 EF 根据其基类处理所有派生的“测试”类。
我尝试忽略 OnModelCreating 方法中不起作用的类型。我考虑过创建一个自定义 EntityTypeConfiguration ,其中包括 SampleTest 的映射,但我还没有找到一种方法来映射回没有鉴别器的同一个表。我在这里考虑过 EF 约定,但我不确定这是否能解决问题。
我可以尝试使用方法而不是派生类来实现它,类似于下面的代码,但我不觉得那样优雅或可维护。我不想沿着这些思路探索选项。
public class Factory {
public static Sample CreateSample() {
return new Sample() { Name = "Test1" };
}
}
public void Test() {
var sample1 = Factory.Create<Sample>();
var sample2 = Factory.Create<Sample>();
sample2.Name == "Custom Name for Test";
}
任何帮助将不胜感激。
【问题讨论】:
-
EF really 不能很好地处理继承 - 这是the Object-Relational-Impedance-Mismatch problem 的核心,也是为什么这么多 ORM 表面上看起来不错,但超出简单的 1:1 的原因类/表设计。现在,您使用的是数据库优先还是代码优先?你在使用迁移吗?
-
“因为实体对象非常复杂,所以配置所有实体所需的字段是一项艰巨的任务” - 您实际上并没有在您发布的代码中“配置任何字段”,请执行你的意思是定义测试数据?你知道有一些工具可以为你做到这一点,比如 Mockaroo?
-
@dai - 我们使用代码优先,没有迁移。没错,我会定义测试数据。
标签: .net automated-tests entity-framework-6