如何模拟实体经理

时间:2015-06-24 17:13:45

标签: c# unit-testing

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

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

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

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

但是因为它存在,我没有看到在没有重构的情况下模拟管理器的方法。

有解决此问题的最佳做法吗?我为这个有点天真的问题道歉,但我只是想确保我在项目的其他部分走正确的道路。

1 个答案:

答案 0 :(得分:2)

我在这里听到两个问题:

我应该模拟EdiEntityManager吗?

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

如何模拟EdiEntityManager?

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

  1. 为正在调用的一个方法(ng-if)创建一个具有已知行为的模拟。
  2. 将该模拟注入此测试的包含对象。
  3. 对于这些努力中的任何一项,发现可能阻止这种情况发生的因素。每个这样的发现要么涉及到对类型和模拟的更多了解,要么将揭示重构的必要性以允许可测试性。发布的代码没有透露。

    例如,假设在构造函数中创建了GetFileRowEntitiesToProcess()

    EdiEntityManager

    这将阻止嘲弄,因为它妨碍了上面的第2步。相反,构造函数将被重构为要求而不是实例化:

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

    这将允许测试提供模拟,并符合依赖性倒置原则。

    或许public SomeObject(EntityManager ediEntityManager) { this.EdiEntityManager = ediEntityManager; } 太具体了,难以模拟/注入,那么实际的类型应该是EntityManager定义的接口。有这个问题的最坏情况可能是你根本不控制类型,只需要定义一个包装器对象(它本身有一个可模拟的接口)来包含EntityManager依赖项。