Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to assert that two list contains elements with the same public properties in NUnit?

Tags:

I want to assert that the elements of two list contains values that I expected, something like:

var foundCollection = fooManager.LoadFoo(); var expectedCollection = new List<Foo>()  {     new Foo() { Bar = "a", Bar2 = "b" },     new Foo() { Bar = "c", Bar2 = "d" } };  //assert: I use AreEquivalent since the order does not matter CollectionAssert.AreEquivalent(expectedCollection, foundCollection); 

However the above code will not work (I guess because .Equals() does not return true for different objects with the same value). In my test, I only care about the public property values, not whether the objects are equal. What can I do to make my assertion?

like image 426
Louis Rhys Avatar asked Aug 29 '12 05:08

Louis Rhys


People also ask

How do I compare two objects in Nunit?

Just install ExpectedObjects from Nuget, you can easily compare two objects's property value, each object value of collection, two composed object's value and partial compare property value by anonymous type. Reference: ExpectedObjects github. Introduction of ExpectedObjects.

What is assert that in Nunit?

Asserts that a condition is true. If the condition is false the method throws an AssertionException. That(Object, IResolveConstraint) Apply a constraint to an actual value, succeeding if the constraint is satisfied and throwing an assertion exception on failure.


2 Answers

REWORKED ANSWER

There is a CollectionAssert.AreEqual(IEnumerable, IEnumerable, IComparer) overload to assert that two collections contain the same objects in the same order, using an IComparer implementation to check the object equivalence.

In the scenario described above, the order is not important. However, to sufficiently handle also the situation where there are multiple equivalent objects in the two collections, it becomes necessary to first order the objects in each collection and use one-by-one comparison to ensure that also the number of equivalent objects are the same in the two collections.

Enumerable.OrderBy provides an overload that takes an IComparer<T> argument. To ensure that the two collections are sorted in the same order, it is more or less required that the types of the identifying properties implement IComparable. Here is an example of a comparer class that implements both the IComparer and IComparer<Foo> interfaces, and where it is assumed that Bar takes precedence when ordering:

public class FooComparer : IComparer, IComparer<Foo> {     public int Compare(object x, object y)     {         var lhs = x as Foo;         var rhs = y as Foo;         if (lhs == null || rhs == null) throw new InvalidOperationException();         return Compare(lhs, rhs);     }      public int Compare(Foo x, Foo y)     {         int temp;         return (temp = x.Bar.CompareTo(y.Bar)) != 0 ? temp : x.Bar2.CompareTo(y.Bar2);     } } 

To assert that the objects in the two collections are the same and comes in equal numbers (but not necessarily in the same order to begin with), the following lines should do the trick:

var comparer = new FooComparer(); CollectionAssert.AreEqual(     expectedCollection.OrderBy(foo => foo, comparer),      foundCollection.OrderBy(foo => foo, comparer), comparer);     
like image 103
Anders Gustafsson Avatar answered Oct 20 '22 00:10

Anders Gustafsson


No, NUnit has no such mechanism as of current state. You'll have to roll your own assertion logic. Either as separate method, or utilizing Has.All.Matches:

Assert.That(found, Has.All.Matches<Foo>(f => IsInExpected(f, expected)));  private bool IsInExpected(Foo item, IEnumerable<Foo> expected) {     var matchedItem = expected.FirstOrDefault(f =>          f.Bar1 == item.Bar1 &&         f.Bar2 == item.Bar2 &&         f.Bar3 == item.Bar3     );      return matchedItem != null; } 

This of course assumes you know all relevant properties upfront (otherwise, IsInExpected will have to resort to reflection) and that element order is not relevant.

(And your assumption was correct, NUnit's collection asserts use default comparers for types, which in most cases of user defined ones will be object's ReferenceEquals)

like image 36
k.m Avatar answered Oct 20 '22 00:10

k.m