What's the Best Way to Compare Double and Int

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).

How does Assert.AreEqual compare two objects in .net unit tests?

The official documentation is pretty laconical and doesn't explain it, so I believe that if the objects are not primitives, then their references will be compared.

That is, two references to the same object would evaluate as being equal; two clones of a same object would evaluate as being different. Unless you overload the Equals() instance method of the class(es) those objects belong to, or the == operator for said class(es).

Also see Reed Copsey's answer.

assert that all fields in 2 objects are the same c#

You could either use records (c# 9 +) or you have to override the Equals method (if you have access and you can change the objects that you're working with).
Records example:

var point = new Point(3, 4);
var point2 = new Point(3, 4);

var test = point.Equals(point2); //this is true

public record Point(int X, int Y);

with classes:

public class Point
{
public int X { get; }
public int Y { get; }

public override bool Equals(object? obj)
{
if (obj == null)
return false;

return obj is Point point && (point.X == X && point.Y == Y);
}

public override int GetHashCode()
{
return HashCode.Combine(X, Y);
}
}

if you are not allowed to touch the implementation, then you could use serialization and compare the strings:

var obj1Str = JsonConvert.SerializeObject(object1);
var obj2Str = JsonConvert.SerializeObject(object2);
Assert.Equal(obj1Str, obj2Str);

using Newtonsoft.Json nuget

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));

Assert to compare two lists of objects C#

Just incase someone comes across this in the future, the answer was I had to create an Override, IEqualityComparer as described below:

public class MyPersonEqualityComparer : IEqualityComparer<MyPerson>
{
public bool Equals(MyPerson x, MyPerson y)
{
if (object.ReferenceEquals(x, y)) return true;

if (object.ReferenceEquals(x, null)||object.ReferenceEquals(y, null)) return false;

return x.Name == y.Name && x.Age == y.Age;
}

public int GetHashCode(MyPerson obj)
{
if (object.ReferenceEquals(obj, null)) return 0;

int hashCodeName = obj.Name == null ? 0 : obj.Name.GetHashCode();
int hasCodeAge = obj.Age.GetHashCode();

return hashCodeName ^ hasCodeAge;
}

}

How to test if two collections of objects are in a different order based on one of the objects' properties?

To determine if the cards are in the same order by using the Id property, you can simply select that property into an IEnumerable and then use the System.Linq extension method SequenceEqual on them:

// Where 'unshuffled' and 'shuffled' are both 'List<Card>' objects
var areEqual = unshuffled.Select(c => c.Id).SequenceEqual(shuffled.Select(c => c.Id));

Alternatively, you could overried Equals and GetHashCode on the Card class, and then use that for the equality comparison. This will help with other card comparisons that may be needed:

public class Card : IEquatable<Card>
{
public int Id { get; set; }

public bool Equals(Card other)
{
return Id == other?.Id;
}

public override bool Equals(object obj)
{
return Equals(obj as Card);
}

public override int GetHashCode()
{
return Id;
}
}

Now our comparison code is slightly more simple:

var areEqual = unshuffled.SequenceEqual(shuffled);

How to test two objects in xunit using FluentAssertions

Looking at your usage of tuples, you're using a recent .NET version. This gives you access to record, which I recommend you use for your Cell structure.

public record struct Cell (char Value);

Records come with an implied constructor and equality comparison. The equality comparison is important for you, because to compare two Matrix objects, you would need to make sure the content of their Cell[,] are identical.

You now have two options:

1. Should().Equal()

Works on IEnumerable. So if you want to compare two Matrix objects, you want to expose the contents of your Cell[,] arrays and compare the two. You use Equal() because you want to compare the order of items. Don't use BeEquivalentTo() because it doesn't care about order. See here for the different enumerable comparisons.

public class Matrix {
...
// Expose your array as an IEnumerable
public IEnumerable<Cell> Cells => _matrix.OfType<Cell>();
}

// And compare the contents in sequence
public void Test(){
// These have 1 Mine in the same location:
Matrix m1 = new(4,4); m1.SetMine(new(1,1));
Matrix m2 = new(4,4); m2.SetMine(new(1,1));
// 1 Mine in a different location:
Matrix xx = new(4,4); xx.SetMine(new(2,2));

// Same contents in the same order
m2.Cells.Should().Equal(m1.Cells);
// Same contents different order, are NOT Equal
xx.Cells.Should().NotEqual(m1.Cells);
// But are Equivalent
xx.Cells.Should().BeEquivalentTo(m1.Cells);

}

2. Should().Be()

If you want to be strict with encapsulation, and don't want to expose the contents of your Cell[,] as public, then you're going to have to define your equality comparison between 2 Matrix objects. This allows you to use Be() which will call the object's Equals() method.

(Here's a full fiddle of the code below)

public class Matrix {
...
/* Easiest way to compare two Cell collections is to join
the chars into a string, and perform string comparison.

We could go through the two arrays and compare the contents
one by one, but a good programmer is a lazy one.
*/
private string CellsAsString() // private so the public can't see it
=> string.Concat(_matrix.OfType<Cell>().Select(c => c.Value));

/* Now Override the Equality comparison of the Object */
public override bool Equals(object other)
=> this.CellsAsString().Equals((other as Matrix)?.CellsAsString());
// Note that we can access private methods of another object
// as long as it's the same class as `this`.

}

Your comparison will now simply be:

Matrix m1 = new(4,4); m1.SetMine(new(1,1));
Matrix m2 = new(4,4); m2.SetMine(new(1,1));
Matrix xx = new(4,4); xx.SetMine(new(2, 2));

m2.Should().Be(m1);
xx.Should().NotBe(m1);


Related Topics



Leave a reply



Submit