C# 我可以使用NUnit';比较不同类型的对象吗;s EqualTo()。是否使用()?

C# 我可以使用NUnit';比较不同类型的对象吗;s EqualTo()。是否使用()?,c#,nunit,icomparer,C#,Nunit,Icomparer,我希望能够使用NUnit的Assert将IConvertible与DateTime中的任意两个内容进行比较。这是,最好不要创建自定义约束。我有一个简单的IComparer,它能很好地完成这个任务。它与EqualTo()一起工作。使用(),只要实际类型和预期类型相同。看起来,EqualsConstraint的AdjustArgumentIfNeeded方法在我的IComparer开始工作之前未能通过断言 我该怎么做才能允许任何形式的测试Assert.That(实际的,Is.EqualTo(预期的)

我希望能够使用NUnit的
Assert将
IConvertible
DateTime
中的任意两个内容进行比较。这是
,最好不要创建自定义约束。我有一个简单的
IComparer
,它能很好地完成这个任务。它与
EqualTo()一起工作。使用()
,只要实际类型和预期类型相同。看起来,
EqualsConstraint
AdjustArgumentIfNeeded
方法在我的
IComparer
开始工作之前未能通过断言

我该怎么做才能允许任何形式的测试
Assert.That(实际的,Is.EqualTo(预期的)。使用(DateTimeComparer.Instance))如果实际和预期可以转换为同一日期时间,则通过,否则失败

这里有一个MCVE,它显示了两个测试,当我比较从不同格式字符串转换的日期时通过,但当比较转换的日期和实时日期时失败

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方法中找到:

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;
}

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

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

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;
}

如果两个参数都是字符串或都不是字符串,则返回true,但如果一个参数是字符串而另一个参数不是字符串,则返回true(字符串是IEnumerable,通过
IEnumerable
)。如果CanCompare返回false,它甚至不会进入自定义比较器查看参数是否相等,框架将运行默认的比较逻辑。我不认为CanCompare在与任何基本的
使用(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);
    }
}
公共类DateTimeComparer:IComparer
{
公共静态只读DateTimeComparer实例=新建DateTimeComparer();
公共整数比较(IConvertible x,IConvertible y)
{
var dateTime1=Convert.ToDateTime(x);
var dateTime2=Convert.ToDateTime(y);
返回日期时间1.CompareTo(日期时间2);
}
}

进一步调查后,我发现正确的行为已经实现,只是在默认的
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);
    }
}
公共类DateTimeComparer:IComparer
{
公共静态只读DateTimeComparer实例=新建DateTimeComparer();
公共整数比较(IConvertible x,IConvertible y)
{
var dateTime1=Convert.ToDateTime(x);
var dateTime2=Convert.ToDateTime(y);
返回日期时间1.CompareTo(日期时间2);
}
}

目前我的解决方法是对所有实际值和预期值调用
ToString()
。这显然是一个骇客行为,让我面临可能的文化问题(因为仍有一些人将“02/08/2016”解读为2月份的某个时间…),但它目前正在发挥作用。我目前的解决方法是调用
ToString()
,查看我所有的实际值和预期值。这显然是有问题的,让我面临可能的文化问题(因为仍然有一些人在2月份的某个时候读到“02/08/2016”),但它现在起作用了。是的,我敢打赌这不是Charlie对这段代码的想法。也许应该是“如果其中一个是可数的,而另一个不是”。即使如此,如果提供了使用
CanCompare
功能,也应该跳过它。很好!SOMBOID将其归档。:-)存档于。抱歉花了这么长时间,我完全忘了!我目前工作不足,所以我将尝试构建NUnit,编写一些测试等。但在我能够构建之前,我不会声明这个问题。很抱歉,我无法接受。你的回答仍然有用。但是另一种实现(使用通用适配器而不是普通适配器)对未来的寻求答案者更有帮助。是的,我敢打赌这不是Charlie对这段代码的想法。也许应该是“如果其中一个是可数的,而另一个不是”。即使如此,如果提供了使用
CanCompare
功能,也应该跳过它。很好!SOMBOID将其归档。:-)存档于。抱歉花了这么长时间,我完全忘了!我目前工作不足,所以我将尝试构建NUnit,编写一些测试等。但在我能够构建之前,我不会声明这个问题。很抱歉,我无法接受。你的回答仍然有用。但是替代的实现(使用通用适配器而不是普通适配器)对未来的寻求答案者更有帮助。或者使用
IComparer
帮助(当没有其他共同祖先时)。或者使用
IComparer
帮助(当没有其他共同祖先时)。