Search code examples
c#mstestfluent-assertions

Fluent assertion, ThenBeInAscendingOrder propertyExpression


I can't make it work, any help will be much apreciated. There is a list of entities from query response where I would like to test if they are in particular order, and I wish to make the comparison with Fluent assertion library but I have been struggling for hours with the solution. So far I got this:

var prop = typeof(BgTaskListItemDto).GetProperty(orderableAttribute);

listResponse.Data.Entities
     .Select(e => prop.GetValue(e))
     .Should().BeInDescendingOrder()
     .And
     .ThenBeInAscendingOrder(
           e => Expression.Property(               
               Expression.Constant(object:e,
                                   type:typeof(BgTaskListItemDto)),
                                   propertyName:nameof(BgTaskListItemDto.Id)));

where orderableAttribute

is from [DataTestMethod],[DataRow(nameof(BgTaskListItemDto.AccountId))]

evaluating the expression property self return valid data, like:

Expression.Property(Expression.Constant(e, typeof(BgTaskListItemDto)), nameof(BgTaskListItemDto.Id))

or even:

var x = Expression.Lambda(Expression.Property(Expression.Constant(e, typeof(BgTaskListItemDto)), nameof(BgTaskListItemDto.Id))).Compile();

returns value where the e.g.: Id can be found, but using it as parameter for ThenBeInAscendingOrder throw exception:

System.ArgumentException: 
Expression <Property(Constant(e, BgTaskDTOs.BgTaskListItemDto), "Id")> cannot be used to select a member. (Parameter 'expression')

What am I missing? What is the proper use for that method?

Thanks in advance!


Solution

  • You should be able to just write the expression as you would any other lambda. Try performing the projection as part of .BeInDescendingOrder() instead of calling .Select() first — FluentAssertions typically gives the most informative assertion messages if you avoid using .Select() entirely.

    var prop = typeof(BgTaskListItemDto).GetProperty(orderableAttribute);
    
    listResponse.Data.Entities
         .Should().BeInDescendingOrder(e => prop.GetValue(e))
         .And.ThenBeInAscendingOrder(e => e.Id);
    

    Expression.Lambda and its related methods are most useful for metaprogramming. If you're reaching for those methods just to do something statically-typed, you have very likely missed a much easier solution.