How to Compare Two Objects in Unit Test

C# - Asserting two objects are equal in unit tests

You've got two different Board instances, so your call to Assert.AreEqual will fail. Even if their entire contents appear to be the same, you're comparing references, not the underlying values.

You have to specify what makes two Board instances equal.

You can do it in your test:

Assert.AreEqual(expected.Rows.Count, actual.Rows.Count);
Assert.AreEqual(expected.Rows[0].Cells[0], actual.Rows[0].Cells[0]);

// Lots more tests of equality...

Or you can do it in your classes: (note I wrote this on-the-fly - you'll want to adjust this)

public class Board
{
public List<Row> Rows = new List<Row>();

public override bool Equals(object obj)
{
var board = obj as Board;

if (board == null)
return false;

if (board.Rows.Count != Rows.Count)
return false;

return !board.Rows.Where((t, i) => !t.Equals(Rows[i])).Any();
}

public override int GetHashCode()
{
// determine what's appropriate to return here - a unique board id may be appropriate if available
}
}

public class Row
{
public List<int> Cells = new List<int>();

public override bool Equals(object obj)
{
var row = obj as Row;

if (row == null)
return false;

if (row.Cells.Count != Cells.Count)
return false;

if (row.Cells.Except(Cells).Any())
return false;

return true;
}

public override int GetHashCode()
{
// determine what's appropriate to return here - a unique row id may be appropriate if available
}
}

Compare two class objects in C#

Assert.Equal relies on the object's .Equals method (see here). When creating your own classes, you have an option to override this method and add your own logic of comparing two objects equality (e.g., field by field equality checking).

If you do not override it, there is a default .Equals inherited from Object, which is equivalent to .ReferenceEquals: it returns true if the two objects have the same reference and false otherwise. The only situation when the two objects have the same reference is when it's the same object.

In your case, you can either define the .Equals override for your class (e.g., see here) or you can try to follow some of the advice given in this SO answer on how to perform deep equality checking of two objects. Third option is to create a separate class inherited from IEqualityComparer, which will purely provide the equality checking logic for your object while not being a part of your class codebase (for example, see this article).

Swift Unit Testing: Checking for equality of two objects of the same class

Look at Equatable protocol. E.g.

extension MyClass: Equatable
{
static func ==(lhs: MyClass, rhs: MyClass) -> Bool
{
return (lhs.property1 == rhs.property1) && (lhs.allData == rhs.allData)
}
}

How to test equality of two objects in unit tests?

Your second approach is much better than the other two, because it keeps tests-specific code together with unit tests, and also because it lets you change your definition of what it means for two View-Models to be equal.

It's hardly worth it to move equality comparers into a separate project, though: if you intend to share equality comparison logic, then you might as well put it into your objects. If, on the other hand, it is designed only for testing, then you should keep it together with the tests (i.e. use your approach #1).

The approach based on serialization is too fragile, because it relies on an unrelated feature (i.e. serialization) to test the feature that you are actually testing (i.e. conversion).

C# Comparing Multiple Objects in Unit Testing without Overriding

So as not to override the Equals method, you would typically create an implementation of IEqualityComparer<T> where T is the type you want to compare, in your case Product.

In the comparer you have to implement the bool Equals(T x, T y) and int GetHashCode(T obj) methods.

Yours may look something like:

public class ProductComparer : IEqualityComparer<Product>
{
// Implement Equals and GetHashCode
}

Then you can use it like this:

var actual = new List<int>();
var expected = new List<int>();
var comparer = new ProductComparer();

Assert.That(actual, Is.EqualTo(expected).Using(comparer));

Proper way to compare object in a Unit test

Property-by-property comparison needs to be repeated in every test - so it's a good old code duplication, a test smell described in XUnitPatterns. Better have a proper equals().

Of course, you can add an utility method personEquals() or even override Person.equals() in runtime. For mocked class, you will probably have to. I personally stick to shorter code which is just one assertEquals() when possible.

How to compare complex objects with NUnit Unit Test

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



Related Topics



Leave a reply



Submit