我可以使用 NUnit 的 EqualTo().Using() 来比较不同类型的对象吗?

Can I compare objects of different types using NUnit's EqualTo().Using()?

我希望能够使用 NUnit 的 Assert.That 比较 IConvertibleDateTime 中的任何两个事物,最好不要创建自定义约束。我有一个简单的 IComparer 可以很好地解决问题。它适用于 EqualTo().Using(),只要实际和预期的类型相同 。看起来 EqualsConstraintAdjustArgumentIfNeeded 方法在我的 IComparer 开始工作之前断言失败了。

如果 actual 和 expected 可以转换为相同的日期时间,我该怎么做才能让 Assert.That(actual, Is.EqualTo(expected).Using(DateTimeComparer.Instance)); 形式的任何测试通过,否则失败?

这是一个 MCVE,当我比较从不同格式字符串转换的日期时显示两个测试通过,但在比较转换后的日期与真实 DateTime 时失败。

using NUnit.Framework;
namespace NunitTest
{
    public class DateTimeComparer : IComparer
    {
        public static readonly DateTimeComparer Instance = new DateTimeComparer();

        public int Compare(object x, object y)
        {
                var dateTime1 = Convert.ToDateTime(x);
                var dateTime2 = Convert.ToDateTime(y);
                return dateTime1.CompareTo(dateTime2);
        }
    }

    [TestFixture]
    public class DateTimeComparerTest
    {
        [Test]
        public void TestComparerUsingString()
        {
            // Passes
            Assert.That("2 August 2016",
                        Is.EqualTo("02/08/2016")
                          .Using(DateTimeComparer.Instance));
        }

        [Test]
        public void TestComparerUsingDateTime()
        {
            // Passes
            Assert.That(new DateTime(2016, 8, 2),
                        Is.EqualTo(new DateTime(2016, 8, 2))
                          .Using(DateTimeComparer.Instance));
        }

        [Test]
        public void TestComparerUsingExpectedDateTime()
        {
            // Fails
            Assert.That("2 August 2016",
                        Is.EqualTo(new DateTime(2016, 8, 2))
                          .Using(DateTimeComparer.Instance));
        }

        [Test]
        public void TestComparerUsingActualDateTime()
        {
            // Fails
            Assert.That(new DateTime(2016, 8, 2),
                        Is.EqualTo("2 August 2016")
                          .Using(DateTimeComparer.Instance));
        }
    }
}

调试显示Compare方法在两个通过的情况下进入,在两个失败的情况下没有进入。

这是一个您必须在 NUnit 中提交才能完全解决的问题。我相信在 CanCompare 方法的 EqualityAdapter.cs 中可以找到观察到的行为的原因:

public virtual bool CanCompare(object x, object y)
{
    if (x is string && y is string)
        return true;

    if (x is IEnumerable || y is IEnumerable)
        return false;

    return true;
}

如果参数都是字符串或都不是字符串,则此 returns 为真,但如果一个是字符串而另一个不是(字符串是一个 IEnumerable,通过 IEnumerable<char>)。如果 CanCompare returns false 它甚至不会进入您的自定义比较器以查看参数是否相等并且框架将 运行 默认比较逻辑。我不认为 CanCompare 在与任何基本 Using(IComparer) 类型约束一起使用时会被覆盖。

经过进一步调查,我发现正确的行为已经实现,只是不在默认 EqualityAdapter 中。使用任何通用适配器都可以。也就是说,将问题中的比较器更改为这样可以使测试通过:

public class DateTimeComparer : IComparer<IConvertible>
{
    public static readonly DateTimeComparer Instance = new DateTimeComparer();

    public int Compare(IConvertible x, IConvertible y)
    {
        var dateTime1 = Convert.ToDateTime(x);
        var dateTime2 = Convert.ToDateTime(y);
        return dateTime1.CompareTo(dateTime2);
    }
}