我希望能够使用NUnit' IConvertible
将DateTime
与Assert.That
的任何两件事进行比较,最好不要创建自定义约束。我有一个简单的IComparer
可以很好地完成这个伎俩。它适用于EqualTo().Using()
,,只要实际和预期属于同一类型。在EqualsConstraint
完成工作之前,AdjustArgumentIfNeeded
IComparer
方法看起来失败了。
如果实际和预期可以转换为相同的日期时间,那么我可以做什么来允许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
方法,并且未在两个失败案例中输入。
答案 0 :(得分:1)
这是您必须在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;
}
如果参数既是字符串又不是字符串,则返回true,但如果一个是字符串而另一个不是字符串,则返回true(字符串是通过IEnumerable<char>
的IEnumerable)。如果CanCompare返回false,它甚至不会进入自定义比较器以查看参数是否相等,框架将运行默认比较逻辑。我不相信CanCompare在与任何基本Using(IComparer)
类型约束一起使用时会被覆盖。
答案 1 :(得分:1)
经过进一步调查后,我发现已经实施了正确的行为,而不是默认的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);
}
}