【问题标题】:Loading related data by foreign key in mocked EF6 database在模拟的 EF6 数据库中通过外键加载相关数据
【发布时间】:2014-02-05 22:20:40
【问题描述】:

最近我开始了一个模拟各种神经网络应用程序的项目。为了处理涉及的大量数据,我使用实体框架模型优先方法实现了一个 SQL-Server 后端。
此外,我越来越喜欢测试驱动开发 (TDD) 学科。但是为了做到这一点,我需要一个模拟数据库来运行我的测试。经过大量搜索,我发现了多种商业和开源解决方案。在这一点上,值得注意的是,当谈到与数据库相关的主题时,我还是个新手。因此,我选择将内存模拟中描述的 msdn 用于 EF6 框架,如here 所述。

Pff,现在我们已经摆脱了背景,这是我的问题:

我已经创建了我的模型并从中生成了数据库。真正的接口层的代码生成是由edmx完成的。为了进行单元测试,我遵循了上述教程并调整了相关字段以匹配我的数据库模型。 (可以找到http://i.imgur.com/julse1Y.png?1,不幸的是我没有代表在帖子中包含图片......)。
但是我不需要每次测试的所有数据,只需要一些子集。我想要一种情况,我可以在测试的设置中指定要加载哪些表以及加载依赖项的深度。

我遇到的问题是在指定相关外键时,相关数据没有与当前DBSet一起加载。例如,在为 Connection 集设置数据时,我希望条目链接到相关数据,在本例中为 Node 集的元素:

var context = new TestContext();

context.NodeSet.Add(new Node { NodeID = 1 });
context.NodeSet.Add(new Node { NodeID = 2 });

context.ConnectionSet.Add(new Connection { ConnID = 1, ToNodeID = 1, FromNodeID = 2 });

var conn = context.ConnectionSet.First();
var fromNode = conn.FromNode;
var toNode = conn.ToNode;

在此示例中,指定 Connection 的 FromNode 属性返回 null。理想的情况是,mock 能够将 ToNodeID 键与相关对象相关联。此外,我希望加载顺序与解决关键约束 i.a.w. 相关。为了解析 FromNode 字段,对应的 Node 必须存在。

我愿意接受有关此特定问题的所有建议,但如果你们中的任何人知道模拟 EF6 模型优先数据库设计的更具建设性的方法。

提前致谢!

【问题讨论】:

  • 这只是一个建议,但您可以使用 Node 的子类而不是基本 POCO Node,并且子类将手动实现导航属性,以便通过 id 引用相关类。
  • 一个有效的建议,但我希望模拟实现导航属性与自身相关对象之间的关系。否则,我将不得不为数据库中的每个表手动创建子类并实现其导航属性。谢谢你的建议,我会用它作为后备。
  • 如果你够聪明,你可以模拟 Add 方法,这样每当你添加 Node 时,Add 都会在内部包装它(使用城堡代理或类似方法)并将包装添加到内部集合中。我从来没有尝试过,并计划很快做,也想知道是否有已知的方法。
  • 不要嘲笑,真的。针对实时数据库运行的代码的区别只是too many。假设你完成它。下一个挑战可能是如何在上下文中禁用延迟加载或成员不是虚拟时禁用延迟加载。后来你开始想知道如何伪造DbFunctions,或者考虑不支持的CLR方法或强制转换,然后...... - 在涉及数据访问的地方进行集成测试(使用测试数据库),在不支持的地方进行纯单元测试'吨。诚然,维护一个测试数据库是一项艰巨的工作,但错误的绿色测试是可怕的。
  • @GertArnold:如果您的某个模拟由于某种原因失败,则总是会发生错误的绿色测试。要么你接受模拟不是真正的实现这一事实,要么你根本反对模拟。正如您所说,缺乏适当的集成测试可能是一个问题,但是让所有访问数据的测试作为集成测试听起来有点过头了(正如您所说的“艰苦的工作”)。

标签: c# database entity-framework unit-testing mocking


【解决方案1】:

在讨论和重新思考问题之后,我认为最简单的方法是忘记 ID 的自动解决,而是在测试之前手动设置引用。

换句话说,如果您有两个 dbset,ChildParent,并且每个子实体都指向一个父实体,那么您就有

public class Child
{
   public int ID_PARENT { get; set; }
   public virtual Parent Parent { get; set; }
}

然后你用数据设置你的模拟

var mockedContext = ... ; // create mocked context with mocked DbSets as
                          // shown in the article you refer to

Child c = new Child();

Parent p = new Parent();
c.Parent = p;  // set up the relation manually

mockedContext.Child.Add( c );
mockedContext.Parent.Add( p );

// property resolving works now as you have set it up in an explicit way
// note that IDs are irrelevant
var children = mockedContext.Child.Where( c => c.Parent != null && c.Parent.Name.StartsWith( "n" ) );

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 2019-10-15
    • 1970-01-01
    • 2012-12-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多