recursive assert on collection

好久不见. 提交于 2019-12-10 09:11:05

问题


I would like a test like this one:

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

to pass. My real case is more complicated, but solving this one in a generic way will do. Any ideas?


回答1:


There's a useful LINQ operator called SequenceEqual() which compares two sequences for equality. SequenceEqual() walks through any two IEnumerable<> sequences and verifies that they have the same number of elements and that elements at the same index are equal (using the default equality comparer). However, since you have nested collections, you need to extend the concept of equality to apply to them as well. Fortunately, there's an overload that allows you supply your own IEqualityComparer<> object.

Since it's awkward to constantly have to define a class to provide equality semantics, I've written a generic extension that allows you to use a delegate instead. Let's look at the code:

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

Now, we can compare two sequences easily enough:

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



回答2:


You could write an extension method like the one below.

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

The problem is of course how to compare this two lists. I would suggest to step through the elements of the one list and try to remove them from the other. If there is a problem while doing this or at the end there are objects left they are not similar.




回答3:


It's an old question, but somebody just posted a link on the nunit-discuss list, so I'll answer.

NUnit is designed to report the two lists as equal. That's just how it works. The Assert.NotEqual should in fact fail.



来源:https://stackoverflow.com/questions/4185164/recursive-assert-on-collection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!