C# 如何测试在域对象中调用其他方法的方法

C# 如何测试在域对象中调用其他方法的方法,c#,.net,unit-testing,C#,.net,Unit Testing,使用域对象时,通常如何对调用对象中另一个方法的方法进行单元测试?例如: public class Invoice { public IList<InvoiceLine> InvoiceLines; public string Company; public bool IsDiscounted; public DateTime InvoiceDate; //... public GetTotalAmt(); public GetExtendedTotalAm

使用域对象时,通常如何对调用对象中另一个方法的方法进行单元测试?例如:

public class Invoice
{
  public IList<InvoiceLine> InvoiceLines;
  public string Company;
  public bool IsDiscounted;
  public DateTime InvoiceDate;
  //...
  public GetTotalAmt();
  public GetExtendedTotalAmt();

  public decimal GetTotalAmt()
  {
    decimal total;
    foreach (InvoiceLine il in InvoiceLines)
    {
      total += il.Qty * il.Price;
    }
    return total;
  }

  public decimal GetExtendedTotalAmt()
  {
    decimal discount;
    if (IsDiscounted)
      discount = .05M; 
    return GetTotalAmt() * discount;
  }
}
公共类发票
{
公共保险公司发票;
上市公司;
公布公共预算;
公共日期时间发票日期;
//...
公共gettotalam();
public GetExtendedTotalAmt();
公共十进制GetTotalAmt()
{
十进制总数;
foreach(发票行中的发票行il)
{
合计+=一笔数量*一笔价格;
}
返回总数;
}
公共十进制GetExtendedTotalAmt()
{
十进制折扣;
如果(已计算)
折扣=0.05百万;
返回getTotalAt()*折扣;
}
}
单元测试getTotalAt()很容易,但使用GetExtendedTotalAmt()时,我必须使用存根/模拟发票行对象使其工作,而我真正想做的就是测试如果IsDiscounted标志为true,是否应用了折扣

其他人是如何处理的?我认为拆分域对象没有意义,因为这些方法都被认为是核心发票功能的一部分(拆分它可能会导致开发人员更频繁地调用错误的方法)


谢谢

您可以将
gettotalam
方法
虚拟化
,然后:

var sut = new MockRepository().PartialMock<Invoice>();
sut.Expect(x => x.GetTotalAmt()).Return(10);
sut.Replay();

var result = sut.GetExtendedTotalAmt();
var sut=new MockRepository().PartialMock();
sut.Expect(x=>x.gettotalam()).Return(10);
sut.Replay();
var result=sut.GetExtendedTotalAmt();

我会建立一个尽可能简单的情况:只有一个数量和价格为1的发票行

大概是这样的:

invoice.Add(new InvoiceLine(new Article("blah", 1M), 1));

Assert.AreEqual(0.95M, invoice.GetExtendedTotalAmt());

当你发现这些东西变得相当复杂,发现错误变得困难等等,那么这就是你应该拆分类的标志(让发票上的计算成为一种策略或类似的东西)。但是只要它像你这里的代码一样简单,我就不会担心它。

是的,rhino mocks,对不起,我应该提到这一点。这是一种相当侵入性的方式,因为许多方法需要是虚拟的,类不是密封的等。你可以使用
TypeMock
来模拟非虚拟方法,但它不是免费的。