Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to compare complex objects with NUnit Unit Test

Learning how to write unit tests with NUnit.

Struggling to compare two complex objects.

There is an answer to a very similar question here Comparing Two objects using Assert.AreEqual() though it looks like you're expected to override Equals() on your objects - this isn't ideal given how many objects there could be, that you would like to compare, let alone the number of properties that could exist on the objects and their nested objects.

Given the sample object:

   public class AMockObject
   {
       public int Id { get; set; }
       public ICollection<int> Numbers { get; set; }

       public AMockObject()
       {
          Numbers = new List<int>();
       }           
    }

I would like to compare that two separate instances of this object have the same values and am finding Assert.AreEqual() isn't really doing what I expected.

For example, all of these fail:

// Example 1
AMockObject a = new AMockObject();
AMockObject b = new AMockObject();
Assert.AreEqual(a,b); // Fails - they're not equal

// Example 2
AMockObject a = new AMockObject() { Id = 1 };
AMockObject b = new AMockObject() { Id = 1 };
Assert.AreEqual(a, b); // Also fails

// Example 3
AMockObject a = new AMockObject() { Id = 1 };
a.Numbers.Add(1);
a.Numbers.Add(2);
a.Numbers.Add(3);    
AMockObject b = new AMockObject() { Id = 1 };
b.Numbers.Add(1);
b.Numbers.Add(2);
b.Numbers.Add(3);    
Assert.AreEqual(a, b); // also fails

We have code in place where we're cloning various objects and some of them a very large. Given this is a pretty common thing to do is there an equally common way to test that two objects are the same at the property-value level?

The example here has two properties. In the real world I have an object with a couple dozen properties, some of which are lists of other complex objects.

For the time being, I am serializing the objects and comparing the strings though this feels less than ideal.

like image 530
Darren Wainwright Avatar asked Sep 03 '25 05:09

Darren Wainwright


1 Answers

There is a tool used in unit testing called Fluent Assertions which is capable of doing such comparisons.

Note however

Objects are equivalent when both object graphs have equally named properties with the same value, irrespective of the type of those objects. Two properties are also equal if one type can be converted to another and the result is equal. The type of a collection property is ignored as long as the collection implements System.Collections.IEnumerable and all items in the collection are structurally equal. Notice that actual behavior is determined by the global defaults managed by FluentAssertions.AssertionOptions.

using FluentAssertions;

//...

// Example 1
AMockObject a = new AMockObject();
AMockObject b = new AMockObject();
a.ShouldBeEquivalentTo(b); // Asserts that an object is equivalent to another object.

// Example 2
AMockObject a = new AMockObject() { Id = 1 };
AMockObject b = new AMockObject() { Id = 1 };
a.ShouldBeEquivalentTo(b); //Asserts that an object is equivalent to another object.

// Example 3
AMockObject a = new AMockObject() { Id = 1 };
a.Numbers.Add(1);
a.Numbers.Add(2);
a.Numbers.Add(3);    
AMockObject b = new AMockObject() { Id = 1 };
b.Numbers.Add(1);
b.Numbers.Add(2);
b.Numbers.Add(3);
a.ShouldBeEquivalentTo(b)    
a.Numbers.ShouldAllBeEquivalentTo(b.Numbers); // Asserts that a collection of objects is equivalent to another collection of objects.

Documentation here

like image 170
Nkosi Avatar answered Sep 04 '25 20:09

Nkosi