[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(新元(10),五次(2));测试失败并出现错误:
预计:TDDbooks.Dollar
但是:TDDbooks.Dollar
答案 0 :(得分:11)
Assert.AreEquals
方法将使用Equals
方法来测试相等性。 {1}}类型不是覆盖Object.Equals
,而是定义一个不参与.Net对象相等的新Dollar
方法。因此它没有被使用,测试使用失败的引用相等。要解决此问题,您需要覆盖equals
方法
Object.Equals
答案 1 :(得分:4)
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();
}
答案 2 :(得分:0)
有几件事:
equals
,而不是覆盖基类方法Equals
。切换到覆盖,NUnit将调用您的方法。 ToString
打印出对象,而ToString的默认实现是简单地打印类名。覆盖ToString
以打印金额,断言消息将更有意义。答案 3 :(得分: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
关键字。
答案 4 :(得分:0)
最好的解决方案已由少数人提供,但有一种替代方案可能适用于其他情况。您需要为amount
字段添加一个getter,如下所示:
public int Amount { get { return amount; } }
然后当你进行单元测试时,它看起来像:
Assert.AreEqual(10, five.times(2).Amount);
现在您要将int
与另一个int
进行比较。或者,您可以将amount
变量公开,但这会破坏封装。在这种情况下,显然正确使用Equals
方法是更好的方法,但在某些情况下,这可能更合适。