我是单元测试的新手,刚刚开始为现有的代码库编写单元测试。
我想为类的以下方法编写一个单元测试。
public int ProcessFileRowQueue()
{
var fileRowsToProcess = this.EdiEntityManager.GetFileRowEntitiesToProcess();
foreach (var fileRowEntity in fileRowsToProcess)
{
ProcessFileRow(fileRowEntity);
}
return fileRowsToProcess.Count;
}
问题在于GetFileRowEntitiesToProcess();
实体管理器是实体框架上下文的包装器。我已经对此进行了搜索,发现一个解决方案是使用已知状态的测试数据库进行测试。但是,在我看来,在测试代码中创建一些实体会产生更一致的测试结果。
但是因为它存在,我没有看到在没有重构的情况下模拟管理器的方法。
有解决此问题的最佳做法吗?我为这个有点天真的问题道歉,但我只是想确保我在项目的其他部分走正确的道路。
答案 0 :(得分:2)
我在这里听到两个问题:
我应该模拟EdiEntityManager吗?
是。它是被测试代码外部的依赖项,它的创建和行为是在该代码之外定义的。因此,出于测试目的,应注入具有已知行为的模拟。
如何模拟EdiEntityManager?
我们无法从发布的代码中了解到。这取决于该类型是什么,如何创建和提供给包含对象等。要回答这部分问题,您应该尝试:
ng-if
)创建一个具有已知行为的模拟。对于这些努力中的任何一项,发现可能阻止这种情况发生的因素。每个这样的发现要么涉及到对类型和模拟的更多了解,要么将揭示重构的必要性以允许可测试性。发布的代码没有透露。
例如,假设在构造函数中创建了GetFileRowEntitiesToProcess()
:
EdiEntityManager
这将阻止嘲弄,因为它妨碍了上面的第2步。相反,构造函数将被重构为要求而不是实例化:
public SomeObject()
{
this.EdiEntityManager = new EntityManager();
}
这将允许测试提供模拟,并符合依赖性倒置原则。
或许public SomeObject(EntityManager ediEntityManager)
{
this.EdiEntityManager = ediEntityManager;
}
太具体了,难以模拟/注入,那么实际的类型应该是EntityManager
定义的接口。有这个问题的最坏情况可能是你根本不控制类型,只需要定义一个包装器对象(它本身有一个可模拟的接口)来包含EntityManager
依赖项。