How to Compare Lists in Unit Testing

How to compare Lists in Unit Testing

To make assertions about collections, you should use CollectionAssert:

CollectionAssert.AreEqual(expected, actual);

List<T> doesn't override Equals, so if Assert.AreEqual just calls Equals, it will end up using reference equality.

Compare two List which in Unit test

It is enough Equal and GetHashCode methods. Then CollectionAssert.AreEqual will work as you expected

public class User 
{
public string Name { get; set; }
public string Password { get; set; }

public override bool Equals(object obj)
{
var user = obj as User;
return user != null &&
Name == user.Name &&
Password == user.Password;
}

public override int GetHashCode()
{
var hashCode = 1290039854;
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Name);
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(Password);
return hashCode;
}
}

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 do I compare two list in expect function of flutter unit testing?

You can use the method ListEquality().equals() to check if two List are equal.

import 'package:collection/collection.dart';

List<int> l1 = [1,2,3];
List<int> l2 = [1,2,3];
final bool equal = ListEquality().equals(l1, l2);
expect(equal, true);

Compare two Liststring[] objects in C# Unit Test

It is failing because the items in your list are objects (string[]) and since you did not specify how CollectionAssert.AreEqual should compare the elements in the two sequences it is falling back to the default behavior which is to compare references. If you were to change your lists to the following, for example, you would find that the test passes because now both lists are referencing the same arrays:

var first = new string[] { "John", "Smith", "200" };
var second = new string[] { "John", "Smith", "200" };

List<string[]> expected = new List<string[]> { first, second};
List<string[]> actual = new List<string[]> { first, second};

To avoid referential comparisons you need to tell CollectionAssert.AreEqual how to compare the elements, you can do that by passing in an IComparer when you call it:

CollectionAssert.AreEqual(expected, actual, StructuralComparisons.StructuralComparer);

Comparing two ArrayLists in UNit Tests

The issue here is that CollectionAssert.AreEqual() will be comparing the elements using Equals().

For reference types that do not override Equals(), that will do a reference comparison. This is not what you want.

Fortunately, you can work around this because CollectionAssert.AreEqual() has an overload that lets you specify a comparer.

Thus, all you need to do is create a comparer which returns zero if two of the elements are equal, and non-zero if they are not. This is slightly complicated by the fact that an ArrayList stores objects, so you need to cast to the right type to make the comparison.

(Note that this is somewhat of an abuse of IComparer since it is
supposed to return -ve, 0 or +ve to provide an ordered comparison of
the left and right hand sides. However, CollectionAssert.AreEqual()
only uses it to test for equality, so it is enough for us to return
zero or non-zero in our implementation.

The AreEqual() method would ideally use an
IEqualityComparer<T>
to compare the elements, but I think that postdates AreEqual() so it
wasn't available at the time that AreEqual() was written.)

Assuming that your elements are of type string[] (which you say they are) then you can create a comparer to compare the elements as follows:

var comparer = Comparer<object>.Create((a, b) => ((string[]) a).SequenceEqual((string[]) b) ? 0 : 1);

Then you can pass that comparer to AreEqual().

An example will make this clear:

ArrayList list1 = new ArrayList();
ArrayList list2 = new ArrayList();

list1.Add(Enumerable.Range( 0, 10).Select(n => n.ToString()).ToArray());
list1.Add(Enumerable.Range(10, 10).Select(n => n.ToString()).ToArray());
list1.Add(Enumerable.Range(20, 10).Select(n => n.ToString()).ToArray());

list2.Add(Enumerable.Range( 0, 10).Select(n => n.ToString()).ToArray());
list2.Add(Enumerable.Range(10, 10).Select(n => n.ToString()).ToArray());
list2.Add(Enumerable.Range(20, 10).Select(n => n.ToString()).ToArray());

var comparer = Comparer<object>.Create((a, b) => ((string[]) a).SequenceEqual((string[]) b) ? 0 : 1);
CollectionAssert.AreEqual(list1, list2, comparer);

This assert will succeed, but to prove that this will detect differences, change the last list2.Add() to list2.Add(Enumerable.Range(20, 9).Select(n => n.ToString()).ToArray()); and the assert will fail.

How can I compare two lists with xunit test

This has to do with object equality.

MyObject does not implement the Equals method. By default you get a reference equality. I assume you have two different objects for MyObject.

Meaning it does not matter that your List holds the similar object(meaning with same values) they are not of the same reference, so your test checks that, this is why it fails.

internal class MyObject
{
{
public char Modifier { get; set; }
public string Name { get; set; }
public string Type { get; set; }

}
}

[Fact]
public void ListMyObject()
{
var list1 = new List<MyObject>
{
new MyObject{ }
};
var list2 = new List<MyObject>
{
new MyObject{ }
};

Assert.Equal(list1, list2); // Fails
}

When we update our class to this.

internal class MyObject
{
public char Modifier { get; set; }
public string Name { get; set; }
public string Type { get; set; }
//When i add this to my class.
public override bool Equals(object obj)
{
return this.Name == ((MyObject)obj).Name;
}
}

Also as mentioned in the comments by Jonathon Chase.

It is a good idea to override the GetHashCode() method as well. It is preferred to inherit from IEquatable<T> so you can avoid casting.

Everything goes green.

        [Fact]
public void ListMyObject()
{
var list1 = new List<MyObject>
{
new MyObject{ Name = "H" }
};
var list2 = new List<MyObject>
{
new MyObject{ Name = "H" }
};

Assert.Equal(list1, list2); //Passes
}


Related Topics



Leave a reply



Submit