NUnit测试Bug?预期<MyType>但是<MyType>

Sta*_*lli 10 c# nunit unit-testing

[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));
}
Run Code Online (Sandbox Code Playgroud)

美元等级

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

在线Assert.AreEqual(新元(10),五次(2)); 测试失败并出现错误:

预计:TDDbooks.Dollar

但是:TDDbooks.Dollar

Jar*_*Par 11

Assert.AreEquals方法将使用该Equals方法来测试相等性.相反,覆盖的Object.EqualsDollar类型只是定义了一个新的equals,不参与.NET对象平等法.因此它没有被使用,测试使用失败的引用相等.要解决此问题,您需要覆盖该Object.Equals方法

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

  return amount == other.amount;
}
Run Code Online (Sandbox Code Playgroud)


Ser*_*kiy 5

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

public override string ToString()
{
   return "$" + amount;
}
Run Code Online (Sandbox Code Playgroud)

现在输出将如下所示:

Expected: $10 
But was: $10
Run Code Online (Sandbox Code Playgroud)

下一个问题是美元比较。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;
}
Run Code Online (Sandbox Code Playgroud)

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

public override int GetHashCode()
{
  return amount.GetHashCode();
}
Run Code Online (Sandbox Code Playgroud)

  • 此外,如果您不打算从 `Dollar` 类派生,请考虑将其设为 `sealed`。如果你不让它`密封`,考虑在`Equals`方法中说`if (GetType() != other.GetType()) return false;`。否则,如果 `other` 是更派生类型的 `Dollar`,比如 `DescriptionDollar`,你可能会得到糟糕的结果。 (2认同)