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

2

7

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?

Craigcraighead answered 2/7, 2018 at 16:24 Comment(2)
There doesn't seem to be a ThenInAscendingOrder so you might have to resort to source.OrderBy(x => x.Ref).ThenBy(x => x.Name).ShouldBeEquivalentTo(results, options => options.WithStrictOrdering()); or something more verbose which checks the order explicitly.Viridian
Before assertions you usually create an expected value(colleciton in your case). Then as mentioned above FluentAssertions have WithStrictOrdering option that check that actual collection equivalent to and ordered as expected.Disallow
C
8

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);
Craigcraighead answered 10/7, 2018 at 8:33 Comment(0)
D
2

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);
}
Dickens answered 3/7, 2018 at 13:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.