我不熟悉单元测试和NUit。 我只是在本书中输入一些引用Java和JUnit的例子。但我正在使用C#。
问题是:我有一个使用覆盖方法的类,例如Equals()
和GetHashCode()
,但当我尝试将此类的两个对象与Assert.AreEqual()
我的代码进行比较时没有被调用,所以我得到了一个例外。
Assert.True(MyClass.Equals(MyClass2))
确实运作良好。但我不想使用这种结构而不是Assert.AreEqual()
。问题出在哪里?
这是班级:
public class Money
{
public int amount;
protected string currency;
public Money(int amount, string currency)
{
this.amount = amount;
this.currency = currency;
}
public new bool Equals(object obj)
{
if (obj == null)
return false;
Money money = (Money)obj;
return (amount == money.amount)
&& (Currency().Equals(money.Currency()));
}
public new int GetHashCode()
{
return (string.Format("{0}{1}", amount, currency)).GetHashCode();
}
public static Money Dollar(int amount)
{
return new Money(amount, "USD");
}
public static Money Franc(int amount)
{
return new Money(amount, "CHF");
}
public Money Times(int multiplier)
{
return new Money(amount * multiplier, currency);
}
public string Currency()
{
return currency;
}
}
测试方法本身:
[TestFixture]
public class DollarTest
{
[Test]
public void TestMultiplication()
{
Money five = Money.Dollar(5);
Assert.True(Money.Dollar(10).Equals(five.Times(2))); // ok
Assert.AreEqual(Money.Dollar(10), five.Times(2)); // fails
}
}
答案 0 :(得分:31)
问题是你隐藏等于,而不是覆盖它。干得好 - 您的单元测试发现了一个错误:)
您的代码应为:
public override bool Equals(object obj)
{
Money money = obj as Money;
if (money == null)
return false;
return (amount == money.amount && currency == money.currency);
}
(如果你给它错误的类型,这将防止它抛出异常。)
我也使字符串相等测试更简单 - 运算符重载可能非常有用:)
顺便说一句,你几乎肯定想:
Currency
更改为属性,而不是方法Amount
属性amount
的类型更改为decimal
而不是int
Times
Equals
方法?我建议你得到一本新书,如果是这样的话(除非它是一个故意的例子,当它错误使用隐藏时!)......这本书是什么?
答案 1 :(得分:1)
我发现实现IEquatable接口也很困惑,该接口也有
Equals(T other)
方法,给我带来了与上述相同的问题。
我选择使用上面的IEquaytable接口覆盖Equals方法的唯一原因是不必进行类型检查。
最后我不得不使用以下代码
public bool Equals(CustomTag other)
{
return (other.Name.Trim().ToLower() == Name.Trim().ToLower());
}
public override bool Equals(object o)
{
if (o is CustomTag)
{
return Equals(o as CustomTag);
}
return false;
}
然后我想,为什么不离开IEquatable接口,只覆盖Equals方法。 (少代码=更好)
答案 2 :(得分:0)
我怀疑你的问题是你没有重写重载了equality ==运算符。在引擎盖下,Assert.AreEqual可能正在使用==。
请参阅Operator Overloading Tutorial。
更新:我通过调试器运行了NUnit测试,它确实使用了Equals方法而不是==运算符。
答案 3 :(得分:0)
您可以使用名为Should的库编写框架无关的断言。它还有一个非常好的流利语法,如果你喜欢流畅的界面,可以使用它。我有一篇与之相关的博客文章。
http://nileshgule.blogspot.com/2010/11/use-should-assertion-library-to-write.html