FluentAssertions:自定义双比较器

FluentAssertions: Custom Double Comparer

提问人:ProtonFisher 提问时间:4/5/2023 更新时间:4/6/2023 访问量:87

问:

我尝试开始使用 FluentAssertions,但很快我就遇到了问题。我将它与 MSTest 一起使用。下面的测试失败了不应该发生的事情(从我的角度来看)。

[TestMethod]
        public void DoubleTest()
        {
            double temp1 = 0.1 - 0.025;
            double temp2 = 0.075;

            temp1.ShouldBeEquivalentTo(temp2, options => options.Using<double>
            (a => a.Subject.HasMinimalDifference(a.Expectation, 1)).WhenTypeIs<double>());
        }

public static bool HasMinimalDifference(double value1, double value2, int units)
   {
      long lValue1 = BitConverter.DoubleToInt64Bits(value1);
      long lValue2 = BitConverter.DoubleToInt64Bits(value2);

      // If the signs are different, return false except for +0 and -0.
      if ((lValue1 >> 63) != (lValue2 >> 63))
      {
         if (value1 == value2)
            return true;

         return false;
      }

      long diff = Math.Abs(lValue1 - lValue2);

      if (diff <= (long) units)
         return true;

      return false;
   }

HasMinimalDifference(哈斯最小差异)

我做了相当多的研究,但我的印象是 Fluent Assertions 忽略了自定义的双比较器。还是只有我?我真的很想使用自定义的双比较器,因为将来可能会通过上面的 MS 示例进行扩展。 任何帮助将不胜感激。

C# 单元测试 精度 mstest fluent-assertions

评论

0赞 Guru Stron 4/5/2023
无法重现 - 我的尝试
1赞 ProtonFisher 4/5/2023
对不起,我的坏@Guru。我忘了提到我目前正在 V4.19.4 上运行。

答:

0赞 Jonas Nyrup 4/5/2023 #1

这里似乎正在发生两件事。

1) 期望执行断言的操作。Using

Using<TProperty>(Action<IAssertionContext<TProperty>> action)

您可以使用 解决此问题。HasMinimalDifference(a.Subject, a.Expectation, 1).Should().BeTrue()

2) 由于您正在使用,因此您必须运行 v4.19.4 或更早版本,因为我们在 v5 中删除了该方法。ShouldBeEquivalentTo

我可以在 v4.19.4 中重现该错误。

您遇到了一个错误,其中未对根对象应用自定义断言。 该错误已在 https://github.com/fluentassertions/fluentassertions/pull/1033 中修复,并作为 v5.7.0 的一部分发布。

[TestMethod]
public void DoubleTest()
{
    object temp1 = 0.1 - 0.025;
    object temp2 = 0.075;

    temp1.Should().BeEquivalentTo(temp2, options => options
        .Using<double>(a => HasMinimalDifference(a.Subject, a.Expectation, 1).Should().BeTrue())
        .WhenTypeIs<double>());
}

public static bool HasMinimalDifference(double value1, double value2, int units)
{
    long lValue1 = BitConverter.DoubleToInt64Bits(value1);
    long lValue2 = BitConverter.DoubleToInt64Bits(value2);

    // If the signs are different, return false except for +0 and -0.
    if ((lValue1 >> 63) != (lValue2 >> 63))
    {
        if (value1 == value2)
            return true;

        return false;
    }

    long diff = Math.Abs(lValue1 - lValue2);

    if (diff <= (long)units)
        return true;

    return false;
}

我还没有研究过什么计算,但这里有一种惯用的方法,可以对所有双打进行轻松的比较。文档HasMinimalDifference

[TestMethod]
public void DoubleTest()
{
    object temp1 = 0.1 - 0.025;
    object temp2 = 0.075;

    temp1.Should().BeEquivalentTo(temp2, options => options
        .Using<double>(a => a.Subject.Should().BeApproximately(a.Expectation, 1))
        .WhenTypeIs<double>());
}

评论

1赞 ProtonFisher 4/5/2023
嘿@Jonas,非常感谢,这解决了它,并有助于更好地了解在这种情况下发生了什么!
0赞 ProtonFisher 4/6/2023
嘿,乔纳斯,只是一个简短的跟进:我试图避免使用“BeApprox”,因为我不确定在通用情况下应该输入什么作为精度。“HasMinimalDifference”比较最后一个有效位,因此两个双精度之间的差异可以约为这 16 个数量级。'双倍。Epsilon' 作为精度将无法通过测试,因为它很小。Смотритетакже: C# 走向数学