Specification icon indicating copy to clipboard operation
Specification copied to clipboard

Cannot unit test specifications which sort by a Smart enum

Open idormenco opened this issue 1 year ago • 2 comments

I tried writing unit tests on a specification that will sort entities by status which is a SmartEnum but I get the At least one object must implement IComparable exception. If this specification is used to sort EF core entities SQL is generated correctly and there is no exception thrown. Package versions:

  • Ardalis.SmartEnum 8.0.0
  • Ardalis.SmartEnum.EFCore 8.0.0
  • Ardalis.Specification 8.0.0
  • Ardalis.Specifcation.EntityFrameworkCore 8.0.0

Code to reproduce:


public sealed class ASmartEnum : SmartEnum<ASmartEnum, string>
{
    public static readonly ASmartEnum Value1 = new(nameof(Value1), nameof(Value1));
    public static readonly ASmartEnum Value2 = new(nameof(Value2), nameof(Value2));
    public static readonly ASmartEnum Value3 = new(nameof(Value3), nameof(Value3));

    private ASmartEnum(string name, string value) : base(name, value)
    {
    }
}

public class Entity
{
    public ASmartEnum EnumValue { get; set; }
}


public class SpecificationWithOrderBy : Specification<Entity>
{
    public SpecificationWithOrderBy()
    {
        Query.OrderBy(x => x.EnumValue);
    }
}

List<Entity> testCollection =
[
    new Entity() { EnumValue = ASmartEnum.Value1 },
    new Entity() { EnumValue = ASmartEnum.Value2 },
    new Entity() { EnumValue = ASmartEnum.Value3 },
];

var spec = new SpecificationWithOrderBy();
var result = spec.Evaluate(testCollection).ToList();
result.Dump();

using the following statement will fix the problem for the in-memory sorting but fails for EF core sorting

  Query.OrderBy(x => x.EnumValue.Value);

idormenco avatar Jan 22 '24 14:01 idormenco

Hi @idormenco,

Yes, you'll face issues during OrderBy in-memory evaluation for SmartEnum properties. The expressions for OrderBy are stored as Expression<Func<T, object?>> since there is no easy way to store the original type. And that boxing/casting loses the original's type behavior (in this case, the IComparable interface).

There is no simple workaround here, unfortunately. We'll try to refactor the ordering infrastructure for the next major release.

fiseni avatar Jan 22 '24 16:01 fiseni

Thanks a lot for the headsup. Will comment out the tests for now

idormenco avatar Jan 23 '24 08:01 idormenco