收集上的递归断言

时间:2010-11-15 14:15:11

标签: .net collections nunit assert

我想要像这样的测试:

[Test]
    public void TestCollectionAssert ()
    {
        var a1 = new [] { new [] { "a" } };
        var a2 = new [] { new [] { "a" } };

        Assert.AreNotEqual (a1, a2);
        //CollectionAssert.AreEqual (a1, a2);
        CollectionAssert.AreEquivalent (a1, a2);
    }

通过。 我的实际案例更复杂,但以通用方式解决这个问题就行了。 有什么想法吗?

3 个答案:

答案 0 :(得分:2)

有一个名为SequenceEqual()的有用LINQ运算符,它将两个序列进行相等性比较。 SequenceEqual()遍历任意两个IEnumerable<>序列,并验证它们是否具有相同的元素数量和相同索引处的元素相等(使用默认的相等比较器)。但是,由于您具有嵌套集合,因此您还需要扩展相等概念以应用于它们。幸运的是,有一个重载允许您提供自己的IEqualityComparer<>对象。

由于不断定义一个提供相等语义的类很尴尬,我编写了一个允许你使用委托的通用扩展。我们来看看代码:

public static class ComparerExt
{
    private class GenericComparer<T> : IEqualityComparer<T>
    {
        private readonly Func<T, T, bool> m_EqualityFunc;

        public GenericComparer( Func<T,T,bool> compareFunc )
        {
            m_EqualityFunc = compareFunc;
        }

        public bool Equals(T x, T y)
        {
            return m_EqualityFunc(x, y);
        }
    }

    // converts a delegate into an IComparer
    public static IEqualityComparer<T> AreEqual<T>( Func<T,T,bool> compareFunc )
    {
        compareFunc.ThrowIfNull("compareFunc");

        return new GenericComparer<T>(compareFunc);
    }
}

现在,我们可以轻松地比较两个序列:

Assert.IsTrue( 
   // check that outer sequences are equivalent...
   a1.SequenceEqual( a2,
                     // define equality as inner sequences being equal... 
                     ComparerExt.AreEqual( (a,b) => a.SequenceEqual(b) ) );

答案 1 :(得分:0)

您可以编写如下所示的扩展方法。

public class AssertExtension
{
    public bool AreSimilar<T>(this CollectionAssert, IList<T> list1, IList<T> list2)
    {
        // ...
    }
}

问题当然是如何比较这两个列表。我建议逐步浏览一个列表的元素,并尝试将它们从另一个列表中删除。如果在执行此操作时或在结束时存在问题,则存在与之不相似的对象。

答案 2 :(得分:0)

这是一个老问题,但有人刚刚在nunit-discuss列表上发布了一个链接,所以我会回答。

NUnit旨在将两个列表报告为相等。这就是它的工作原理。 Assert.NotEqual实际上应该失败。