Fuff数据库时,Effort- FirstOrDefault返回null


我正在尝试为我的项目创建一些单元测试,经过多次挖掘后我发现了Effort,这个想法很棒,它嘲笑数据库而不是伪造DBContext,顺便说一句,这很难让它正确使用复杂的架构。

但是我试图在我将其专门添加到由Effort创建的内存数据库后获取用户的电子邮件,这里是代码

MyContext contextx = new MyContext(Effort.DbConnectionFactory.CreateTransient());

var client = new Client
{
    ClientId = 2,
    PersonId = 3,
    Person = new Person
    {
        PersonId = 3,
        EMail = "xxxxx@gmail.com"
    }
};
contextx.Client.Add(client); //<-- client got added, I checked it and is there

var email = contextx.Client.Select(c => c.Person.EMail).FirstOrDefault(); 

在上面的最后一行我不能让它返回电子邮件xxxx@gmail.com而是总是返回null。

有任何想法吗?

一般承认的答案

回答你的直接问题

对于您提出的具体问题,我建议两件事:

  1. 看看contextx.Client.ToArray() ,看看你在该集合中真正拥有多少成员。可能是Client集合实际上是空的,在这种情况下,您确实会为null。或者,可能是Client集合中的第一个元素对于EMail具有空值。

  2. 如果在查询DbContext上的Client集合之前调用了contextx.SaveChanges() ,行为会如何变化?我很想知道调用SaveChanges是否会导致新插入的值存在于集合中。这确实不应该是必需的,但是Effort和DbContext之间可能存在一些奇怪的交互。

编辑: SaveChanges()原来是答案。

一般测试建议

由于您使用“单元测试”标签标记了这个问题,我将根据我作为单元测试从业者和教练花费的十年时间提供一些一般的单元测试建议。 单元测试是关于单独测试应用程序的各个小部分。通常,这意味着单元测试只能同时与几个类进行交互。这也意味着单元测试不应该依赖于外部库或依赖项(例如数据库)。相反, 集成测试会立即执行系统的更多部分,并且可能对数据库之类的内容具有外部依赖性。

虽然这看起来似乎是对术语的狡辩,但这些术语对于将测试的实际意图传达给团队中的其他成员非常重要。

在这种情况下,要么您真的想要对依赖于DbContext的某些功能进行单元测试,要么您正在尝试测试您的数据访问层。如果您正在尝试编写一个直接依赖于DbContext的独立单元测试,那么您需要打破对DbContext的依赖。我将在下面的破坏DbContext的依赖关系中解释这一点。否则,您真的尝试集成测试您的DbContext,包括您的实体如何映射。在这种情况下,我总是发现最好隔离这些测试并使用真实(本地)数据库。您可能希望使用与您在生产中使用的相同种类的本地安装的数据库。通常,SqlExpress工作得很好。将测试指向测试可以完全丢弃的数据库实例。在运行每个测试之前,让测试删除所有现有数据。然后,他们可以设置他们需要的任何数据,而无需担心现有数据会发生冲突。

打破DbContext的依赖

那么,当业务逻辑依赖于访问DbContext时,如何编写好的单元测试? 你没有。

在我使用Entity Framework进行数据持久化的应用程序中,我确保对DbContext访问包含在一个单独的数据访问项目中。通常,我将创建实现Repository模式的类,并允许这些类依赖于DbContext 。因此,在这种情况下,我将创建一个实现IClientRepository接口的ClientRepository 。界面看起来像这样:

public interface IClientRepository {

    Client GetClientByEMail(string email);

}

然后,任何需要访问该方法的类都可以使用基本的stub / mock / whatever进行单元测试。没有什么可以担心嘲笑DbContext 。您的数据访问层已包含,您可以使用真实数据库对其进行全面测试。有关如何测试数据访问层的一些建议,请参见上文。

作为额外的好处,此接口的实现定义了在单个统一的位置通过电子邮件地址查找Client的含义。 IClientRepository接口允许您快速回答“我们如何查询系统中的Client实体?”这一问题。

DbContext的依赖与测试问题的大小基本相同,因为允许域类依赖于连接字符串并且在任何地方都有ADO.Net代码。这意味着您必须创建一个包含真实数据的真实数据存储(即使使用虚假数据库)。但是,如果您在特定数据访问程序DbContext包含对DbContext访问权限,则会发现单元测试更容易编写。

就项目组织而言,我通常只允许我的数据访问项目参考实体框架。我将有一个单独的Core项目,我在其中定义实体。我还将在Core项目中定义数据访问接口。然后,具体的接口实现被放入数据访问项目中。您的解决方案中的大多数项目可以简单地依赖于Core项目,只有顶级可执行文件或Web项目才真正需要依赖于数据访问项目。





许可下: CC-BY-SA
不隶属于 Stack Overflow
这个KB合法吗? 是的,了解原因