【问题标题】:NUnit doesn't work well with Assert.AreEqualNUnit 不适用于 Assert.AreEqual
【发布时间】:2011-06-23 21:07:13
【问题描述】:

我是单元测试的新手,尤其是 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
    }
}

【问题讨论】:

  • 你试过公共覆盖 bool Equals() 吗?
  • @Samuel - 正确,但您需要切换修饰符和类型,即 public bool override Equals()

标签: c# unit-testing nunit


【解决方案1】:

问题是你隐藏等于,而不是覆盖它。干得好 - 你的单元测试发现了一个错误:)

你的代码应该是:

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

【讨论】:

  • 这太棒了。美好的一天开始。
  • 是的,这是一个决定!非常感谢。我阅读了 Kent Beck 的“测试驱动开发:示例”。例子是用Java写的,所以方法定义是:public bool equals(Object object);但是我正在编写 C# 代码,所以 IDE-helper 询问我是否想编写“public new bool Equals(object o)”而不仅仅是“public bool Equals(object o)”。所以,这是我的错误,更不用说问题的所有解决方案了。虽然感谢您的提示。我会考虑他们的未来经验;)
  • 啊,对了——那没关系。如果它是一本 C# 书,我会感到沮丧:)
【解决方案2】:

我发现实现 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 方法。 (更少的代码 = 更好)

【讨论】:

    【解决方案3】:

    我怀疑您的问题是您没有 overridden 重载相等 == 运算符。在引擎盖下 Assert.AreEqual 可能正在使用 ==。

    Operator Overloading Tutorial

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

    【讨论】:

    • 您不能覆盖运算符 - 您只能重载它们。 NUnit 几乎可以肯定 不会 使用重载运算符 - 当它可以只调用 Equals 时,它会变得不必要地复杂......
    【解决方案4】:

    您可以使用一个名为 Should 的库来编写与框架无关的断言。它还具有非常好的流畅语法,如果您喜欢流畅的界面,可以使用它。我有一篇与此相关的博客文章。

    http://nileshgule.blogspot.com/2010/11/use-should-assertion-library-to-write.html

    【讨论】:

      猜你喜欢
      • 2021-03-29
      • 2011-04-04
      • 1970-01-01
      • 1970-01-01
      • 2018-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-10
      相关资源
      最近更新 更多