Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NUnit test Bug? Expected <MyType> But was <MyType>

[Test]
public void testMultiplication()
{
    var five=new Dollar(5);
    Assert.AreEqual(new Dollar(10), five.times(2));
    Assert.AreEqual(new Dollar(15), five.times(3));
}

Dollar class

public class Dollar
{
    private int amount;

    public Dollar(int amount)
    {
        this.amount = amount;
    }

    public Dollar times(int multiplier)
    {
        return new Dollar(amount * multiplier);
    }

    public bool equals(Object theObject)
    {
       Dollar dollar = (Dollar) theObject;

       return amount == dollar.amount;
    }
}

On line Assert.AreEqual(new Dollar(10), five.times(2)); test fail with error:

Expected: TDDbooks.Dollar

But was: TDDbooks.Dollar

like image 384
Stalli Avatar asked Oct 22 '12 15:10

Stalli


2 Answers

The Assert.AreEquals method will use the Equals method to test equality. Instead of overriding Object.Equals the Dollar type just defines a new equals method that doesn't participate in .Net object equality. Hence it's not used and the test uses reference equality which fails. To fix this you need to override the Object.Equals method

public override bool Equals(object obj) { 
  Dollar other = obj as Dollar;
  if (other == null) {
    return false;
  }

  return amount == other.amount;
}
like image 179
JaredPar Avatar answered Sep 23 '22 01:09

JaredPar


NUnit displays string representation of objects. In order to have handy output, you should override ToString method of Dollar class:

public override string ToString()
{
   return "$" + amount;
}

Now output will be like:

Expected: $10 
But was: $10

Next problem is dollars comparison. NUnit compare objects by calling Equals method (not equals, but Equals. Kent Beck uses Java in his examples. In C# we have Pascal naming for methods). Default implementation of Equals method return true if objects have same reference. But in Times method you create new instance of Dollar class. In order to fix that, you should change Equals method implementation to compare amount field.

public override bool Equals(object obj)
{ 
  Dollar other = obj as Dollar;
  if (other == null)
    return false;  

  return amount == other.amount;
}

Also notice, that you should use override keyword for overriding base class functionality. And one more thing - when you are overriding Equals functionality, you should override GetHashCode method. In your case it's OK to have something like:

public override int GetHashCode()
{
  return amount.GetHashCode();
}
like image 45
Sergey Berezovskiy Avatar answered Sep 26 '22 01:09

Sergey Berezovskiy