2010-03-14 10 views
32

Sembra che CollectionAssert non possa essere utilizzato con generici. Questo è super frustrante; il codice che voglio testare usa i generici. Che cosa devo fare? Scrivi un boilerplate per convertire tra i due? Controllare manualmente l'equivalenza di raccolta?CollectionAssertire utilizzare con generici?

Questo fallisce:

ICollection<IDictionary<string, string>> expected = // ... 

IEnumerable<IDictionary<string, string>> actual = // ... 

// error 1 and 2 here 
CollectionAssert.AreEqual(expected.GetEnumerator().ToList(), actual.ToList()); 

// error 3 here 
Assert.IsTrue(expected.GetEnumerator().SequenceEquals(actual)); 

errori di compilazione:

di errore 1:

'System.Collections.Generic.IEnumerator>' non contiene una definizione per 'ToList' e nessun metodo di estensione "ToList" che accetta un primo argomento di tipo "System.Collections.Generic.IEnumerator>" potrebbe essere trovato

Errore 2

'System.Collections.Generic.IEnumerator>' non contiene una definizione per 'ToList' e nessun metodo di estensione 'ToList' accettare un primo argomento di tipo 'System.Collections.Generic. IEnumerator>' potrebbe essere trovato

Errore 3

'System.Collections.Generic.IEnumerator>' non contiene una definizione per 'SequenceEquals' e nessun metodo di estensione 'SequenceEquals' accettare un primo argomento di digitare "System.Collections.Generic.IEnumerator>" potrebbe essere trovato

Cosa sto facendo di sbagliato? Non sto usando le estensioni correttamente?

Aggiornamento: Ok, questo sembra un po 'meglio, ma ancora non funziona:

IEnumerable<IDictionary<string, string>> expected = // ... 

IEnumerable<IDictionary<string, string>> actual = // ... 

CollectionAssert.AreEquivalent(expected.ToList(), actual.ToList()); // fails 
CollectionAssert.IsSubsetOf(expected.ToList(), actual.ToList()); // fails 

io non voglio essere il confronto liste; Mi interessa solo impostare l'uguaglianza dei membri. L'ordine dei membri non è importante. Come posso aggirare questo?

+0

Sei sicuro? Mi ha dato errori nel compilatore, che posterò domani mattina. –

+0

Ho sbagliato; CollectionAssert NON funziona su ICollection . Funziona solo con ICollection. Questo è stato richiesto su Connect, ma finora non è stato implementato. Possibile soluzione: http://stackoverflow.com/questions/662458/unittesting-ilist-with-collectionassert –

+0

Se ricordo correttamente, le interfacce ICollection e ICollection sono VASTAMENTE diverse. Questo non è il caso di IEnumerable versus IEnumerable . Si prega di verificare i loro metodi. ICollection è utilizzato per qualcosa di diverso da ICollection . ICollection non ha nemmeno il metodo ADD: è usato per scopi "più di basso livello" come il multithreading e il marshalling. Pertanto, penso che dovresti trovare un'interfaccia che soddisfi meglio le tue esigenze, semplice IEnumerable forse? – quetzalcoatl

risposta

1

È possibile scrivere facilmente la propria versione generica, quindi spostarla in una base o in una classe di utilità utilizzata in tutti i test. Basalo sugli operatori LINQ come Tutti e Tutti.

33

È possibile utilizzare CollectionAssert con raccolte generiche. Il trucco è capire che i metodi CollectionAssert funzionano su ICollection e sebbene poche interfacce di raccolta generiche implementino lo ICollection, List<T>.

Così, è possibile aggirare questa limitazione utilizzando il metodo ToList estensione:

IEnumerable<Foo> expected = //... 
IEnumerable<Foo> actual = //... 
CollectionAssert.AreEqual(expected.ToList(), actual.ToList()); 

Detto questo, continuo a considerare CollectionAssert rotto in molti altri modi, così ho tendono ad usare Assert.IsTrue con i metodi di estensione LINQ, in questo modo:

Assert.IsTrue(expected.SequenceEquals(actual)); 

FWIW, Attualmente sto usando questi metodi di estensione per eseguire altri confronti:

public static class EnumerableExtension 
{ 
    public static bool IsEquivalentTo(this IEnumerable first, IEnumerable second) 
    { 
     var secondList = second.Cast<object>().ToList(); 
     foreach (var item in first) 
     { 
      var index = secondList.FindIndex(item.Equals); 
      if (index < 0) 
      { 
       return false; 
      } 
      secondList.RemoveAt(index); 
     } 
     return secondList.Count == 0; 
    } 

    public static bool IsSubsetOf(this IEnumerable first, IEnumerable second) 
    { 
     var secondList = second.Cast<object>().ToList(); 
     foreach (var item in first) 
     { 
      var index = secondList.FindIndex(item.Equals); 
      if (index < 0) 
      { 
       return false; 
      } 
      secondList.RemoveAt(index); 
     } 
     return true; 
    } 
} 
+0

Questo mi dà errori del compilatore (vedi sopra). –

+1

È necessario importare lo spazio dei nomi System.Linq in una direttiva using. 'ToList' è un metodo di estensione. –

+0

Ho aggiunto 'using System.Linq;' ma non funziona ancora: \t ''System.Collections.Generic.IEnumerator >' non contiene una definizione per ' ToList' e nessun metodo di estensione 'ToList' accettare un primo argomento di tipo 'System.Collections.Generic.IEnumerator >' potrebbero essere found' –

5

Se si sta lavorando con i set, poi utilizzare questo Idiom

HashSet<string> set1 = new HashSet<string>(){"A","B"}; 
HashSet<string> set2 = new HashSet<string>(){"B","A"}; 

Assert.IsTrue(set1.SetEquals(set2));