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 postdatesAreEqual()
so it
wasn't available at the time thatAreEqual()
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
What Value Should I Pass into Timezoneinfo.Findsystemtimezonebyid(String)
Center Messagebox in Parent Form
How to Use the .Net Timer Class to Trigger an Event at a Specific Time
How to Access Session in a Webmethod
How to Deploy a .Net Application That Uses Odac Without Installing the Whole Component to the User
How to Get the Position of Textbox That Has Been Pressed
Xml File Creation Using Xdocument in C#
Linq - Query Syntax VS Method Chains & Lambda
Set Content-Type of Media Files Stored on Blob
Ensure That Httpconfiguration.Ensureinitialized()
What Are the Default Schedulers for Each Observable Operator
How to Get Next (Or Previous) Enum Value in C#
How to Prevent an Exception in a Background Thread from Terminating an Application
How to Check If a Class Inherits Another Class Without Instantiating It
Restoring Window Size/Position with Multiple Monitors
How to Capitalize First Letter of First Name and Last Name in C#