是否有必要模拟注入到方法中的每个类?



我的问题与此类似:我应该在单元测试时模拟所有依赖项吗?

我理解当我的代码访问数据库、Web 服务或文件系统上的文件时嘲笑的好处。 模拟意味着如果存在我无法控制的问题,例如网络问题,那么我的单元测试将通过 - 因为我的代码仍然正确。

但是,假设我有一些这样的代码:

public Offer AssignOffer(OfferType offerType, IOfferValueCalculator valueCalculator) 
{ 
DateTime dateExpiring = offerType.CalculateExpirationDate(); 
int value = valueCalculator.CalculateValue(this, offerType); 

var offer = new Offer(this, offerType, dateExpiring, value); 

_assignedOffers.Add(offer); 

NumberOfActiveOffers++; 

return offer; 
} 

我从这里拿来的:https://github.com/jbogard/presentations/blob/master/WickedDomainModels/After/Model/Member.cs

模拟传递给方法的对象参数是否正常,即 OfferType 和 IOfferValueCalculator(我编写的接口和类)?这些类是我编写的,与Member.AssignOffer位于同一项目中。

我之前问过一个类似的问题;但是它被关闭了,因为基于意见。 我试图通过提供示例代码使这个问题更清晰。

我的问题也与此类似:我什么时候应该嘲笑?

这:https://lostechies.com/jimmybogard/2011/01/07/putting-mocks-in-their-place/和这个:http://www.taimila.com/blog/ddd-and-testing-strategy/似乎只建议嘲笑:"跨越建筑上重要的边界进行模拟,但不在这些边界内"。

是的,如果您模拟报价类型,IOffervalueCalculator,您可以使用报价类型,到期日期等不同组合来测试代码的其他部分。

TL;DR:不,绝对没有必要嘲笑每个注射类型。

通常,您会在单元上下文之外模拟对象。模拟文件系统、数据库等很容易知道,因为您的应用程序和这些外部组件之间的界限非常清晰。

然而,在您的应用程序内部,它不是黑白的。如果您的组件定义良好并且具有明确的边界,则选择要模拟的内容可能很容易。如果这些界限没有明确定义,就很难选择需要嘲笑的东西,在这种情况下,我建议急切地嘲笑。定义不当的上下文边界通常会导致许多依赖关系,而不是可能导致脆弱测试的模拟。

在问题中选择的代码示例中,在简要查看存储库后,我会嘲笑OfferTypeIOfferValueCalculator。我将使用名称的力量来扩展原因:

  • 要测试的类是Member。不知道属于什么背景;
    • 这表示上下文的边界不明确 - 如果不确定,最好将依赖项视为外部依赖项;
  • 该方法的主要任务是"分配报价"。我是否关心外部组件将计算的到期日期,只要我知道方法按预期使用了它?不;
    • 附带问题:为什么分配报价的方法甚至涉及到期日期的计算?这单一的责任是什么?
  • 我会认为IOfferValueCalculator属于与Member相同的上下文我可能不会嘲笑它。但同样 - 我不这么认为,在"分配报价"问题的上下文中,计算值不是一个重要的细节;

总之:在测试中对象和方法使用不同的名称,更好地了解应用程序,我的答案可能会有所不同。现在很难推理什么属于哪里,什么应该取决于什么。

在另一种情况下,我会看到一个由紧密相关的类型组成的简洁集群,与其他集群几乎没有依赖关系,我不太急于嘲笑。

最新更新