NUnit与Assert.AreEqual不兼容

时间:2009-09-03 13:17:25

标签: c# unit-testing nunit

我不熟悉单元测试和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
    }
}

4 个答案:

答案 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