2009-09-03 133 views
11

我是新手,尤其是单元测试和NUit。 我只是在书中提到了一些引用Java和JUnit的例子。但我正在使用C#。NUnit不适用于Assert.AreEqual

的问题是:我有与被覆盖的方法,如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 
    } 
} 
+2

你试过用公共覆盖布尔Equals()吗? –

+0

@Samuel - 正确,但你需要切换修饰符和类型,即公共布尔覆盖Equals() – Fraser

回答

30

的问题是你隐藏平等相待,不首要它。干得好 - 你的单元测试已经发现了一个bug :)

你的代码应该是:

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方法?如果是的话,我建议你买一本新书(除非它是一个故意的例子,当它是错误的使用隐藏!)...是哪本书?

+2

希望这个bug证明了单元测试的价值! – RichardOD

+0

这太棒了。伟大的开始,一天。 –

+0

耶,我是对的:) –

0

我怀疑你的问题是你没有 覆盖 重载的== ==运算符。在引擎盖下,Assert.AreEqual可能使用==。

请参阅Operator Overloading Tutorial

更新:我运行NUnit测试通过调试器,它确实使用Equals方法而不是==运算符。

+2

你不能重载操作符 - 你只能*重载*它们。 NUnit几乎可以肯定*不会使用重载操作符 - 它可以调用Equals时不必要的复杂... –

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方法。 (less code = better)

相关问题