Ilessa
Ilessa

Reputation: 622

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?

Upvotes: 7

Views: 2129

Answers (2)

Ilessa
Ilessa

Reputation: 622

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);

Upvotes: 8

Jonas Nyrup
Jonas Nyrup

Reputation: 2586

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);
}

Upvotes: 2

Related Questions