2010-11-15 3 views
4

Я хотел бы тест, как этот:рекурсивный утверждают на коллекции

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

пройти. Мое реальное дело сложнее, но решение этого в общем случае сделает. Любые идеи?

+1

Что вы спрашиваете ....? –

+0

Должны ли они быть равными или нет? Соответствует ли позиция в массиве? –

+0

Ну, они равны, поэтому я ожидаю, что AreEquivalent будет правдой. – wysek

ответ

0

Вы можете написать метод расширения, подобный приведенному ниже.

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

Проблема заключается, конечно, в том, как сравнить эти два списка. Я бы предложил пройти через элементы одного списка и попытаться удалить их из другого. Если есть проблема при выполнении этого или в конце есть оставленные объекты, они не похожи.

+0

Что вы предлагаете изменить один из в списках я считаю это неприемлемым. Кроме того, удаление элемента вызовет Equals() в любом случае, и оно не будет работать так, как я хочу. :) – wysek

+0

Вы можете избежать изменения одного из списков, сделав его копию, но вы правы, решение не очень удобно. – MatthiasG

2

Существует полезный оператор LINQ, который называется SequenceEqual(), который сравнивает две последовательности для равенства.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))); 
+2

Это, кажется, решает проблему, но она по-прежнему работает только для одноуровневых вложенных коллекций, поэтому не является общим решением :) И в моем реальном случае у меня есть KeyValuePair [] и ваш способ решения проблема кажется слишком сложной. – wysek

+0

@wysek: Итак, когда вы говорите, что ищете универсальное решение *, вы имеете в виду любой уровень гнездования? Это не было ясно в вашем вопросе. Сообщите нам, если это так. – LBushkin

+1

Я скорее искал инструмент, уже существующий ... Но кажется, что его нет. Для этого я внедрил свой собственный универсальный компаратор, но спасибо за это! – wysek

0

Это старый вопрос, но кто-то просто разместил ссылку на NUnit-обсуждения списка, поэтому я отвечу.

NUnit предназначен для представления двух списков как равных. Вот как это работает. Ошибка Assert.NotEqual на самом деле не выполняется.

Смежные вопросы