11

Assert.Equals() never calls

Equals()
operator ==
operator !=

Am I missing something? I have implemented IEquatable but still the methods are never being called while using nunit.

if (objectA != objectB) Assert.Fail(); //doesnt fail
if (!objectA.Equals(objectB)) Assert.Fail(); //doesnt fail
Assert.AreEqual(objectA, objectB); //fail

UPDATE

I should have been clearer.

public class Entity 
{
  public int ID { get; set; }
}

var objectA = new Entity() { ID = 1 };
var objectB = new Entity() { ID = 1 };

two separate instances both with the same ID I have implemented all the relevant methods to make this work for ==, != and Equals but nunit AreSame and AreEqual still fails to call those methods.

bleevo
  • 1,637
  • 2
  • 18
  • 30
  • 1
    I have exactly the same problem. For now I am using Assert.IsTrue(objectA.Equals(objectB)); – Stefano Ricciardi Feb 04 '10 at 11:08
  • I have the same problem and I have determined that it works if the objects I'm comparing are *not* the same reference. ie create 2 objects with different properties apart from the equality compared properties, then Assert.Equals works... If it the same reference is being compared (which are surely equal) then it fails! as not being equal (NUnit 2.5) – PandaWood Jul 28 '16 at 08:02
  • You are looking for `Assert.AreEqual(objA, objB);` – DanielV Aug 03 '16 at 07:23

5 Answers5

11

Use Assert.AreEqual(a, b) for value types, Assert.AreSame(a, b) for reference types. http://www.nunit.org/index.php?p=identityAsserts&r=2.2.7

Xilconic
  • 3,785
  • 4
  • 26
  • 35
Robert
  • 2,964
  • 1
  • 18
  • 16
  • This still says they are not the same for some reason.. (it wont call my equal methods) :( What I am trying to test is 2 instances of the same class with the same ID that should say yes they are equal. – bleevo Jul 06 '09 at 03:41
  • Not sure, you could certainly do Assert.IsTrue(objectA == objectB) but I'm not sure why you need to. – Robert Jul 06 '09 at 03:46
  • 1
    `Assert.AreSame(a, b)` is actually performing `ReferenceEquals(a,b)`, and might not be what you are looking for. If you want to assert the same object instance, than use this method. Otherwise, you could better use `Assert.AreEqual(a,b)` instead. – Xilconic Mar 17 '14 at 14:22
5

You are definitely correct. I was wrestling with a similar problem earlier today, until I found your post and am now sure, that NUnit IsEqualTo() does not consistently call the Equals overrides provided.

I say consistently, because sometimes it does. As a matter of fact I have two classes. The second one derived from the first. When I call Is.EqualTo() on instances of the first, NUnit calls the Equals overrides, for instances of the second it does not.

While that is very peculiar, I have no time to investigate further into what is going on.

People with similar problems or solutions should definitely post about it, as this is a very annoying thing and actually had me doubt the validity of my tests.

In the meantime I created the following Affirm class, which calls the Equals overrides for sure (I checked it). It uses NUnit to do a simple equality Assert instead of Is.EqualTo() and somewhat remedies the fact, that this way NUnit doesn't give string representations of the objects in case the test fails.

So here it is:

using NUnit.Framework;

public static class Affirm
{
    public static Affirmer That(object actual)
    {
        return new Affirmer(actual);
    }
}

[EditorBrowsable(EditorBrowsableState.Never)]
public class Affirmer
{
    readonly object _actual;

    public Affirmer(object actual)
    {
        _actual = actual;
    }

    public void IsEqualTo(object expected)
    {
        string failureMessage = string.Format("\nExpected: <{0}>\nBut was:  <{1}>", _actual, expected);
        Assert.That(_actual.Equals(expected), Is.True, failureMessage);
    }

    public void IsNotEqualTo(object expected)
    {
        string failureMessage = string.Format("\nDid not excpect: <{0}>\nBut was:         <{1}>", _actual, expected);
        Assert.That(_actual.Equals(expected), Is.False, failureMessage);
    }
}

Use it like this:

Affirm.That(actualObject).IsEqualTo(expectedObject);

and

Affirm.That(actualObject).IsNotEqualTo(expectedObject);

Hope this helps.

Community
  • 1
  • 1
Thorsten Lorenz
  • 11,781
  • 8
  • 52
  • 62
  • Just for completeness: As can be seen in your original post (http://stackoverflow.com/questions/1624848/does-nunits-is-equalto-not-work-reliably-for-classes-derived-from-generic-classe), your problem was caused by a bug in your override of object.Equals (object). (I guess this thread's OP's problem was caused by a similar bug.) – Fabian Schmied Aug 18 '10 at 15:14
  • @FabianSchmied I don't think it's due to the bug in the equals method because he states that Nunit never even calls his equals method. I have come here with the same problem. It won't matter what I change in the Equals method if it's not being called by Nunit – PandaWood Jul 28 '16 at 07:42
  • I have the same problem but my test worked before I implemented Equals on the class myself. Something must have convinced NUnit to *not* call my Equals method, now that I have one. I don't think I'm prepared to investigate the code, as I can get it to work by using Assert.IsTrue(obj1.Equals(obj2)) – PandaWood Jul 28 '16 at 07:47
  • @PandaWood Thorsten Lorenz' example had two `Equals` methods: one that takes a parameter of type `object`, one that takes a parameter of a base class type. NUnit called the one with type `object`. This method had a bug: it contained a type check not accounting for subclasses. The solution is to fix that type check. See the [accepted answer](http://stackoverflow.com/a/1625339/62838). – Fabian Schmied Jul 29 '16 at 06:23
3

Some frameworks allow for equality to work differently before the Id is assigned (ie, the Entity is unsaved) than afterwarsd, when its clear that the intent is that the Entity Id is the sole basis for quality. Are you using some sort of framework or is Entity your own class?

If it's your own class can you show the gist of your Equals() logic?

Cheers, Berryl

FYI Assert.AreSame is NEVER a test to validate your implementation of IEquatable! See ReferenceEquals in your help doc to understand that assertion better.

Berryl
  • 12,471
  • 22
  • 98
  • 182
1

It should work (see this related question) if the Equals method was overridden correctly. Could it be a problem with your Equals method (although if it simply consists of int comparison I would think not)? Might be worth setting a break point in your Equals method and then running the test to see what's going on behind the scenes.

Community
  • 1
  • 1
jpoh
  • 4,536
  • 4
  • 35
  • 60
1

You might want to check out this question: NUnit's Assert.Equals throws exception "Assert.Equals should not be used for assertions"

tl;dr; Assert.Equals(obj1, obj2) is overridden by NUnit, and throws an exception. You should use Assert.AreEqual(obj1, obj2) instead.

Community
  • 1
  • 1
Xilconic
  • 3,785
  • 4
  • 26
  • 35