NUnit与Assert.AreEqual不兼容
我是unit testing的新手,尤其是NUit。 我只是在本书中输入一些引用Java和JUnit的例子。 但我正在使用C#。
问题是:我有一个带有重写方法的类,比如Equals()
和GetHashCode()
,但是当我试图用Assert.AreEqual()
比较这个类的两个对象时,我的代码没有被调用,所以我得到了例外。
Assert.True(MyClass.Equals(MyClass2))
确实运行良好。 但我不想使用这种结构而不是Assert.AreEqual()
。 问题出在哪里?
这是class级:
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 } }
问题是你隐藏了 Equals,而不是覆盖它。 做得好 – 你的unit testing发现了一个bug 🙂
你的代码应该是:
public override bool Equals(object obj) { Money money = obj as Money; if (money == null) return false; return (amount == money.amount && currency == money.currency); }
(如果你给它错误的类型,这将防止它抛出exception。)
我已经使字符串相等测试更简单 – 运算符重载可能非常有帮助:)
顺便说一下,你几乎肯定想:
- 将
Currency
更改为属性,而不是方法 - 添加
Amount
属性 - 可能会将
amount
类型更改为decimal
而不是int
- 将字段设为私有和只读
- 密封课程
- 为==和!=添加运算符重载
- 可能会添加*运算符重载以执行与
Times
相同的操作 - 在计算哈希时避免字符串格式化(有数十个答案显示更好的哈希实现)
编辑:我刚刚重读你正在使用书中的一个例子。 这本书是否真的隐藏而不是覆盖Equals
方法? 我建议你买一本新书,如果是这样的话(除非它是一个故意的例子,说明什么时候使用隐藏是错误的 !)……这本书是哪本书?
我发现实现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方法。 (更少的代码=更好)
我怀疑你的问题是你没有重写了使用equality ==运算符的重载。 在引擎盖下,Assert.AreEqual可能正在使用==。
请参阅运算符重载教程 。
更新:我通过调试器运行NUnit测试,它确实使用Equals方法而不是==运算符。
您可以使用名为Should的库编写框架无关的断言。 它还有一个非常漂亮的流利语法,如果您喜欢流畅的界面,可以使用它。 我有一篇与之相关的博客文章。
http://nileshgule.blogspot.com/2010/11/use-should-assertion-library-to-write.html