如何在 FluentAssertions 的集合断言中重用自定义对象断言

Posted

技术标签:

【中文标题】如何在 FluentAssertions 的集合断言中重用自定义对象断言【英文标题】:How to reuse custom object assertion in collection assertion in FluentAssertions 【发布时间】:2019-07-09 00:53:32 【问题描述】:

我已经阅读了FluenAssertions Extensibility 页面,但我仍然无法理解如何为对象集合创建一个Should().BeEquivalentTo() 比较方法,如果我已经为一个对象实现了Should().BeEquivalentTo(),同时保留了所有其他断言方法同一个集合。

这是一个简化的例子: 我要检查的类:

public class CalculationResult

    public DateTime Date  get; set; 
    public int Id  get; set; 
    public bool CalcState  get; set; 
    public double Result  get; set; 

我在 Specflow 测试套件中转换表格行的类

public class CalcResultBdd

    public DateTime Date  get; set; 
    public double Result  get; set; 

类到类比较类是:

public class CalculationResultAssertions : ReferenceTypeAssertions<CalculationResult, CalculationResultAssertions>

    public CalculationResultAssertions(CalculationResult instance)
    
        Subject = instance;
    

    protected override string Identifier => "CalculationResult";

    [CustomAssertion]
    public AndConstraint<CalculationResultAssertions> BeEquivalentTo(
        CalcResultBdd expectedResult,
        double precision = 0.001,
        string because = "",
        params object[] becauseArgs)
    
        Execute.Assertion.
            BecauseOf(because, becauseArgs).
                ForCondition(expectedResult != null).
                FailWith("You cannot assert that calculation result is correct if you do not pass a proper object").
            Then.
                ForCondition(precision >= 0).
                FailWith("You cannot compare double values if you provide negative precision").
            Then.
            Given(() => Subject).
                ForCondition(s => s.CalcState).
                FailWith("Expected CalcState to be \"true\"").
            Then.
                ForCondition(s => s.Date == expectedResult.Date).
                FailWith(
                    "Expected Date to be 0reason, but found 1",
                    _ => expectedResult.Date.ToString("yyyy-MM-dd"),
                    s => s.Date.ToString("yyyy-MM-dd")).
            Then.
                ForCondition(s => Math.Abs(s.Result - expectedResult.Result) <= precision).
                FailWith(
                    "Expected Result to be 0 with precision 1reason, but found 2",
                    _ => expectedResult.Result,
                    _ => precision,
                    s => s.Result);

        return new AndConstraint<CalculationResultAssertions>(this);
    

连接 FluentAssertions 和自定义断言类的静态类:

public static class AssertionExtensions

    public static CalculationResultAssertions Should(this CalculationResult instance)
    
        return new CalculationResultAssertions(instance);
    

如果我运行以下命令,但没有为 List&lt;CalculationResult&gt; 重新定义 BeEquivalentTo

List<CalculationResult> actualResults = /* getting results here */
actualResults.Should().BeEquivalentTo(new CalcResultBdd[]  /* expected results here */ )

FluentAssertions 将使用内置结构比较而不是自定义比较。我是否可以更改我的代码中的某些内容,以便 Fluent 断言使用自定义比较来代替?

【问题讨论】:

【参考方案1】:

如果我没记错的话,BeEquivalentTo 扩展方法期望是通用的,也会取代你的。

【讨论】:

我想你是对的。 FluentAssertions 库不会从库外部查找自定义比较实现(BeBeEquivalentTo)。或者我完全错过了使用库注册自定义实现的方式。 没有注册任何东西的概念。这一切都依赖于编译器选择正确的重载。

以上是关于如何在 FluentAssertions 的集合断言中重用自定义对象断言的主要内容,如果未能解决你的问题,请参考以下文章

FluentAssertions:如何在每对元素上使用自定义比较来比较两个集合?

如何使用 FluentAssertions 测试嵌套集合

FluentAssertions:如何指定该集合应包含一定数量的匹配谓词的元素?

FluentAssertions:如何指定该集合应包含一定数量的匹配谓词的元素?

如何将子集集合按值(结构平等)与 FluentAssertions 进行比较?

FluentAssertions Should.Equal 在集合上,包含空值