如何嘲笑实体经理

本文关键字:实体 何嘲笑 | 更新日期: 2023-09-27 17:59:44

我是单元测试的新手,刚刚开始为现有代码库编写单元测试。

我想为一个类的以下方法编写一个单元测试。

public int ProcessFileRowQueue()
    {
        var fileRowsToProcess = this.EdiEntityManager.GetFileRowEntitiesToProcess();
        foreach (var fileRowEntity in fileRowsToProcess)
        {
           ProcessFileRow(fileRowEntity);
        }
        return fileRowsToProcess.Count;
    }

问题出在GetFileRowEntitiesToProcess();上。实体管理器是实体框架上下文的包装器。我对此进行了搜索,发现一个解决方案是使用已知状态的测试数据库进行测试。然而,在我看来,在测试代码中创建一些实体会产生更一致的测试结果。

但就其存在而言,如果不进行一些重构,我看不出有什么方法可以嘲笑Manager。

是否有解决此问题的最佳实践?我很抱歉这个问题有点天真,但我只想确保我在项目的其余部分走上正确的道路。

如何嘲笑实体经理

我在这里听到两个问题:

我应该嘲笑EdiEntityManager吗

是的。它是测试代码外部的依赖项,它的创建和行为是在代码外部定义的。因此,出于测试目的,应该注入一个具有已知行为的mock。

如何嘲笑EdiEntityManager

我们无法从发布的代码中得知。这取决于该类型是什么,它是如何创建并提供给包含对象的,等等。要回答这部分问题,你应该尝试:

  1. 为被调用的一个方法(GetFileRowEntitiesToProcess())创建一个具有已知行为的mock
  2. 将mock注入到正在测试的包含对象中

对于这两种努力中的任何一种,都要找出可能阻止这种情况发生的原因。每一个这样的发现要么涉及到对类型和mock的更多了解,要么将揭示重构的必要性以允许可测试性。发布的代码并没有透露这一点。

举个例子,假设EdiEntityManager是在构造函数中创建的:

public SomeObject()
{
    this.EdiEntityManager = new EntityManager();
}

这将是防止嘲笑的东西,因为它会妨碍上面的第2步。相反,构造函数将被重构为需要而不是实例化:

public SomeObject(EntityManager ediEntityManager)
{
    this.EdiEntityManager = ediEntityManager;
}

这将允许测试提供mock,并且符合依赖反转原则。

或者EntityManager是一个过于具体的类型,很难模拟/注入,那么实际的类型应该是EntityManager定义的接口。这个问题最糟糕的情况可能是根本不控制类型,只需要定义一个包装器对象(它本身有一个可模拟的接口)来封装EntityManager依赖项。