2016-08-02 65 views
0

我希望能够使用NUnit的Assert.That来比较IConvertibleDateTime之间的任何两件事情,最好不要创建自定义约束。我有一个简单的IComparer,很好地诀窍。它与EqualTo().Using(),一起使用,只要实际和预期的是相同类型。看起来EqualsConstraintAdjustArgumentIfNeeded方法在我的IComparer开始工作之前没有做出断言。我可以使用NUnit的EqualTo()来比较不同类型的对象吗?使用()?

如果实际和预期的实际和预期可以转换为相同的日期时间并且否则失败,我应该怎么做以允许任何形式Assert.That(actual, Is.EqualTo(expected).Using(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方法在两个通过的情况下进入和两个失败的情况下,不进入。

+0

我现在的解决方法是在我所有的实际和预期中调用'ToString()'。这显然是很冒险的,并且让我接触到可能存在的文化问题(因为在二月的某个时候,还有一些人阅读“02/08/2016”......),但它现在还在工作。 –

回答

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); 
    } 
} 
+0

使用'IComparer '可以帮助(当没有其他共同的祖先时)。 – smg

1

这是一个问题,你必须在NUnit中提交才能完全解决。我认为,观察到的行为的原因在EqualityAdapter.cs发现在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是一个字符串,但如果是字符串和其他ISN 't(字符串是通过IEnumerable<char>的IEnumerable)。如果CanCompare返回false,它甚至不会进入您的自定义比较器来查看参数是否相等,并且框架将运行默认比较逻辑。我不相信在使用任何基本的Using(IComparer)类型约束时,CanCompare会被忽略。

+0

是的,我敢打赌,这不是查理在那段代码中想到的。也许它应该是“如果其中一个是IEnumerable而另一个不是”。即使如此,如果提供了“使用”,则应该跳过“CanCompare”。 –

+0

好抓! Sombody将其归档。 :-) – Charlie

+0

归档于[GitHub](https://github.com/nunit/nunit/issues/1897)。对不起,花了这么长时间,我完全忘了它!我目前工作不足,所以我会尝试构建NUnit,编写一些测试等。我不会声称这个问题,直到我可以建立。 –

相关问题