10
[Test]
public void testMultiplication()
{
    var five=new Dollar(5);
    Assert.AreEqual(new Dollar(10), five.times(2));
    Assert.AreEqual(new Dollar(15), five.times(3));
}

美元级

public class Dollar
{
    private int amount;

    public Dollar(int amount)
    {
        this.amount = amount;
    }

    public Dollar times(int multiplier)
    {
        return new Dollar(amount * multiplier);
    }

    public bool equals(Object theObject)
    {
       Dollar dollar = (Dollar) theObject;

       return amount == dollar.amount;
    }
}

上线 Assert.AreEqual(new Dollar(10), Five.times(2)); 测试失败并出现错误:

预期:TDDbooks.Dollar

但是是:TDDbooks.Dollar

4

5 回答 5

11

Assert.AreEquals方法将使用该Equals方法来测试相等性。与其重写类型,不如定义一个不参与 .Net 对象相等性的新方法Object.Equals。因此它没有被使用,并且测试使用了失败的引用相等。要解决此问题,您需要覆盖该方法DollarequalsObject.Equals

public override bool Equals(object obj) { 
  Dollar other = obj as Dollar;
  if (other == null) {
    return false;
  }

  return amount == other.amount;
}
于 2012-10-22T15:15:41.330 回答
5

NUnit 显示对象的字符串表示。为了方便输出,您应该覆盖类ToString的方法Dollar

public override string ToString()
{
   return "$" + amount;
}

现在输出将如下所示:

Expected: $10 
But was: $10

下一个问题是美元比较。NUnit 通过调用Equals方法来比较对象(不是equals,而是Equals。Kent Beck 在他的示例中使用 Java。在 C# 中,我们为方法使用 Pascal 命名)。Equals如果对象具有相同的引用,则方法的默认实现返回 true。但是在Times方法中,您创建了类的新实例Dollar。为了解决这个问题,您应该更改Equals方法实现以比较金额字段。

public override bool Equals(object obj)
{ 
  Dollar other = obj as Dollar;
  if (other == null)
    return false;  

  return amount == other.amount;
}

另请注意,您应该使用override关键字来覆盖基类功能。还有一件事——当你覆盖Equals功能时,你应该覆盖GetHashCode方法。在您的情况下,可以有类似的东西:

public override int GetHashCode()
{
  return amount.GetHashCode();
}
于 2012-10-22T15:18:29.143 回答
0

有几件事:

  1. 您已经定义了一个新方法equals,而不是覆盖基类方法Equals。切换到覆盖,NUnit 将调用你的方法。
  2. NUnit 使用它的 打印出对象ToString,而 ToString 的默认实现是简单地打印类名。覆盖ToString以打印金额和断言消息将更有意义。
于 2012-10-22T15:17:52.003 回答
0

您所断言的new Dollar(10)是与返回的对象相同的对象five.times(2),这是不正确的。

如果你想以这种方式断言,你需要在你的 Dollar 类中重载 Equals 方法,如下所示:

 public override bool Equals(Object obj)
 {
     if (obj is Dollar)
     {
         return this.Amount == ((Dollar)obj).Amount;
     }
     return false;
 }

您没有override在方法中使用关键字Equals

于 2012-10-22T15:23:39.120 回答
0

一些人已经给出了最好的解决方案,但是有一个替代方案可能在其他情况下也有效。您需要为该amount字段添加一个吸气剂,如下所示:

public int Amount { get { return amount; } }

然后当你进行单元测试时,它看起来像:

Assert.AreEqual(10, five.times(2).Amount);

所以现在你正在比较一个int和另一个int。或者,您可以将amount变量公开,但这会破坏封装。显然Equals,在这种情况下,正确使用该方法是更好的方法,但在某些情况下,这可能更可取。

于 2012-10-22T16:38:47.380 回答