我正在开发一个计算复杂系统成本的应用程序(C#)。该系统由许多部分(和子部分)组成,每个部分可能有不同的计算算法。最初,我计划创建一组仅包含属性作为系统部件表示的类。除了这些课程,我还会创建一套专用的成本计算器。它类似于程序编程和贫血领域模型(反模式?)。所以我想到了另一种方法:在那些部分实体中实现成本计算逻辑。但是单元测试会更加困难,因为"更高"零件取决于"更低"份'成本。所以基本上我有这两个选项(假设我的系统是披萨):
a)外部服务中的计算逻辑。贫血领域模型:
public class Pizza
{
public List<BaseIngredient> BaseIngredients { get; set;}
public List<ExtraIngredient> ExtraIngredients {get;set;}
public List<Sauce> Sauces { get; set;}
}
public class PizzaCostCalculator : IPizzaCostCalculator
{
private IBaseIngredientCostCalculator _baseIngredientCostCalculator;
private ISauceCostCalculator _sauceCostCalculator;
public PizzaCostCalculator(IBaseIngredientCostCalculator baseIngredientCostCalculator, ISauceCostCalculator sauceCostCalculator)
{
_baseIngredientCostCalculator = baseIngredientCostCalculator;
_sauceCostCalculator = sauceCostCalculator;
}
public double GetCost(Pizza pizza)
{
double result = 0;
result += _baseIngredientCostCalculator.GetCost(pizza.BaseIngredients)
result += _sauceCostCalculator.GetCost(pizza.Sauces)
// repeat above for extra ingredients etc
result = ApplyDiscount(pizza);
return result;
}
}
b)计算实体内部的登录(如何将披萨与其成分分开进行单元测试?)
public class Pizza
{
public List<BaseIngredient> BaseIngredients { get; set;}
public List<ExtraIngredient> ExtraIngredients {get;set;}
public List<Sauce> Sauces { get; set;}
public double GetCost()
{
double result = 0;
foreach (var baseIngredient in BaseInredient)
{
result += baseIngredient.GetCost();
}
// repeat above for sacues, extra ingredients, etc
result = ApplyDiscount(result);
return result;
}
}
这两种方法的优点和缺点是什么?如果第二个更好,我应该如何进行单元测试呢?
答案 0 :(得分:3)
您可以通过提供模拟成分来单独测试Pizza
的成分。您的模型公开属性以执行此操作:
public List<BaseIngredient> BaseIngredients { get; set;}
public List<ExtraIngredient> ExtraIngredients {get;set;}
public List<Sauce> Sauces { get; set;}
&#34;安排&#34;单元测试的步骤将为这些具有预定义行为的对象创建模拟,在Pizza
实例上设置它们,并调用正在测试的逻辑。
当然,另一种看待这种情况的方法是询问您是否需要分别测试Pizza
成分。有一个&#34;纯粹主义者&#34;视图暗示&#34;每个班级必须独立测试&#34;但是,真的有多必要?如果成分是独立使用的,那么你当然可以为它们创建独立的测试。但看起来Pizza
是一个由其他模型组成的聚合根模型。它的测试可以反映出来。
除非有外部依赖项进行模拟,否则编写单个测试(或一组测试)是完全可以接受的,这些测试运行Pizza
上的计算具有有效成分实例的对象。成分的内部结构将同时进行间接测试。在这种情况下,您实质上正在测试的是系统的面向外部的业务逻辑,而不是系统的每个单独的技术组件。两者都有效。
如果您将测试与实施过于紧密联系,那么您会发现测试难以维护。如果业务运营只关心Pizza
成本并且明确对如何执行该计算感兴趣,那么完全有效的测试就是测试一个顶级业务操作