Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to verify that multiple sorts have been applied to a collection?

I'm implementing sortable columns on my Kendo grid and the user-expected behaviour is to allow multiple columns to be sorted at the same time.

Naturally, I'm starting off by writing a unit test to be able to verify that the sorting is (by default) first by Ref ascending, then Name ascending.

Test suppliers in question are here:

_context.Suppliers.Add(new Supplier { Ref = "abc", Name = "steve"});
_context.Suppliers.Add(new Supplier { Ref = "abc", Name = "bob"});    
_context.Suppliers.Add(new Supplier { Ref = "cde", Name = "ian"});    
_context.Suppliers.Add(new Supplier { Ref = "fgh", Name = "dan"}); 

Then I go and ask the test for my sorted suppliers.

Fluent assertions I know has the BeInAscendingOrder and BeInDescendingOrder methods, however even after looking through the documentation and following possibly related questions I couldn't see an example of chaining sorting methods.

My current test verification is like this:

results.Should().HaveCount(4).And.BeInAscendingOrder(x => x.Ref)
           .And.BeInAscendingOrder(x => x.Name);

I was expecting the verification to work a bit like LINQ where it has OrderBy(x => x.Ref).ThenBy(x => x.Name).

However when running the test, it is failing because it is expecting the collection to be ordered ascending by Name (the final sort assertion).

Is there a way to tell Fluent Assertions that the sorts should be applied in conjunction with one another and not just in sequence?

like image 968
Ilessa Avatar asked Jul 02 '18 16:07

Ilessa


2 Answers

So I tried Fabio/Stuart's comments of using WithStrictOrdering and that worked for a time.

However when I came to change the sort order my tests kept passing instead of failing (because I'd changed the sort on my test but not the method).

The following worked wonderfully:

var resultsList = results.ToList();
var expectedResults = resultsList.OrderByDescending(x => x.IsSupplierInvalid)
                                        .ThenBy(x => x.Ref).ToList();
resultsList.Should().HaveCount(4).And.ContainInOrder(expectedResults);
like image 144
Ilessa Avatar answered Sep 19 '22 17:09

Ilessa


One way is to use this overload of BeInAscendingOrder:

BeInAscendingOrder(IComparer<T> comparer, string because = "", params object[] args)

and then create a SupplierComparer that inherits from Comparer<Supplier>.

Here is a complete example

class Supplier
{
    public string Ref { get; set; }
    public string Name { get; set; }
}

class SupplierComparer : Comparer<Supplier>
{
    public override int Compare(Supplier x, Supplier y)
    {
        var compareRef = x.Ref.CompareTo(y.Ref);
        if (compareRef != 0)
        {
            return compareRef;
        }

        var compareName = x.Name.CompareTo(y.Name);
        if (compareName != 0)
        {
            return compareName;
        }

        return 0;
    }
}

public void MyTestMethod()
{
    var suppliers = new[]
    {
        new Supplier { Ref = "abc", Name = "steve" },
        new Supplier { Ref = "abc", Name = "bob" },
        new Supplier { Ref = "cde", Name = "ian" },
        new Supplier { Ref = "fgh", Name = "dan" }
    };

    var comparer = new SupplierComparer();
    suppliers.Should().BeInAscendingOrder(comparer);
}
like image 35
Jonas Nyrup Avatar answered Sep 20 '22 17:09

Jonas Nyrup