将枚举与自定义 Fluent 断言等效步骤进行比较

Posted

技术标签:

【中文标题】将枚举与自定义 Fluent 断言等效步骤进行比较【英文标题】:Comparing Enums with custom Fluent Assertions Equivalency Step 【发布时间】:2016-06-07 03:37:14 【问题描述】:

我正在尝试为 Fluent Assertions 编写自定义等效步骤,以将主题端的 Enum 值与异常端的字符串进行比较。

我似乎面临的问题是,在我的EquivalencyStep 被调用之前,传递给IEquivalencyStep 的主题类型已转换为字符串。

在试图将枚举直接转换为字符串的流利断言中是否发生了一些神奇的事情?

代码示例如下:

public class SubjectClass

    public EnumType Prop1  get; set; 


public enum EnumType

    A,
    B,
    C


public class ExpectionClass

    public string Prop1  get; set; 


[TestFixture]
public class ComparingEnumWithTests

    [Test]
    public void Test()
    
        var expection = new ExpectionClass() Prop1 = "bbb";

        var subject = new SubjectClass() Prop1 = EnumType.B;

        subject.ShouldBeEquivalentTo(expection, opt => opt.Using(new ComparingEnumWith<EnumType>(new Dictionary<string, EnumType>()
        
            "aaa", EnumType.A ,
            "bbb", EnumType.B ,
            "ccc", EnumType.C 
        )));

    


public class ComparingEnumWith<TEnum> : IEquivalencyStep
    where TEnum : struct

    private readonly IReadOnlyDictionary<string, TEnum> _dictionary;
    private readonly Type _enumType;

    public ComparingEnumWith(IReadOnlyDictionary<string, TEnum> dictionary)
    
        _enumType = typeof(TEnum);
        if (!_enumType.IsEnum)
        
            throw new ArgumentException("TEnum must be an enum");
        

        _dictionary = dictionary;
    

    public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config)
    
        var subjectType = config.GetSubjectType(context);

        return subjectType != null && subjectType == _enumType && context.Expectation is string;
    

    public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator parent, IEquivalencyAssertionOptions config)
    
        var expected = _dictionary[(string)context.Expectation];

        return ((TEnum)context.Subject).Equals(expected);
    

更新:

根据上面的问题,我已将代码修改为以下内容,以防其他人遇到同样的问题。

public class SubjectClass

    public EnumType Prop1  get; set; 


public enum EnumType

    A,
    B,
    C


public class ExpectionClass

    public string Prop1  get; set; 


[TestFixture]
public class ComparingEnumWithTests

    [Test]
    public void Test()
    
        var expection = new ExpectionClass() Prop1 = "bbb";

        var subject = new SubjectClass() Prop1 = EnumType.B;
        AssertionOptions.EquivalencySteps.Insert<ComparingEnumWith<EnumTypeDataMapProvider, EnumType>>();
        subject.ShouldBeEquivalentTo(expection);

    


public interface IEnumDataMapProvider<TEnum>

    IReadOnlyDictionary<string, TEnum> Map  get; 


public class EnumTypeDataMapProvider : IEnumDataMapProvider<EnumType>

    public IReadOnlyDictionary<string, EnumType> Map => new Dictionary<string, EnumType>()
    
        "aaa", EnumType.A,
        "bbb", EnumType.B,
        "ccc", EnumType.C
    ;



public class ComparingEnumWith<TMapProvider, TEnum> : IEquivalencyStep
    where TMapProvider : IEnumDataMapProvider<TEnum>
    where TEnum : struct

    private readonly IReadOnlyDictionary<string, TEnum> _dictionary;
    private readonly Type _enumType;

    public ComparingEnumWith()
    
        _enumType = typeof(TEnum);
        if (!_enumType.IsEnum)
        
            throw new ArgumentException("TEnum must be an enum");
        

        var provider = Activator.CreateInstance<TMapProvider>();

        _dictionary = provider.Map;
    

    public bool CanHandle(IEquivalencyValidationContext context, IEquivalencyAssertionOptions config)
    
        var subjectType = config.GetSubjectType(context);

        return subjectType != null && subjectType == _enumType && context.Expectation is string;
    

    public bool Handle(IEquivalencyValidationContext context, IEquivalencyValidator parent, IEquivalencyAssertionOptions config)
    
        var expected = _dictionary[(string)context.Expectation];

        return ((TEnum)context.Subject).Equals(expected);
    

【问题讨论】:

【参考方案1】:

这是一个错误。您正在注册我们称之为用户等效性步骤的东西。但这些在内置TryConversionEquivalencyStepReferenceEqualityEquivalencyStep 之后运行。如果您可以将此作为错误提交,我们可以查看它。作为一种解决方法,请考虑使用 AssertionOptions.EquivalencySteps.Insert&lt;ComparingEnumWith&lt;T&gt;&gt;(); 在所有内置步骤之前插入您的自定义步骤

【讨论】:

看起来这个问题现在已经解决了,你能确认@Dennis 并更新你的答案吗? Insert 方法会将其放在 内置步骤之前。但多年来一直如此。

以上是关于将枚举与自定义 Fluent 断言等效步骤进行比较的主要内容,如果未能解决你的问题,请参考以下文章

如何将两组与自定义数据类型进行比较

为啥将 std::sort 与自定义比较器一起使用无法编译?

Fluent Assertion 中的对象结构比较方法

在 Fluent 断言中排除未初始化 (null) 的属性

.net测试篇之测试神器Autofixture Generator使用与自定义builder

使用 Fluent NHibernate 和 NHibernate 3 将枚举映射为 Int