2010-03-19 14 views
6

Sono nuovo di NUnit e sto cercando un'esplosione sul motivo per cui questo test fallisce?NUnit, CollectionAssert.AreEquivalent (..., ...), C# Domanda

Ottengo la seguente eccezione durante l'esecuzione del test.

NUnit.Framework.AssertionException: Previsto: equivalente a < < .... ExampleClass>, < .... ExampleClass>> Ma era: < < .... ExampleClass>, < ... .ExampleClass>>

using NUnit.Framework; 
using System.Collections.ObjectModel; 

public class ExampleClass 
{ 
    public ExampleClass() 
    { 
     Price = 0m; 
    } 

    public string Description { get; set; } 
    public string SKU { get; set; } 
    public decimal Price { get; set; } 
    public int Qty { get; set; } 
} 

[TestFixture] 
public class ExampleClassTests 
{ 
    [Test] 
    public void ExampleTest() 
    { 

     var collection1 = new Collection<ExampleClass> 
       { 
        new ExampleClass 
         {Qty = 1, SKU = "971114FT031M"}, 
        new ExampleClass 
         {Qty = 1, SKU = "971114FT249LV"} 
       }; 

     var collection2 = new Collection<ExampleClass> 
       { 
        new ExampleClass 
         {Qty = 1, SKU = "971114FT031M"}, 
        new ExampleClass 
         {Qty = 1, SKU = "971114FT249LV"} 
       }; 

     CollectionAssert.AreEquivalent(collection1, collection2); 

    } 
} 

risposta

10

Per determinare se 2 raccolte sono uguali, NUnit deve infine confrontare i valori all'interno della raccolta. In questo caso i valori sono di tipo ExampleClass che è un class. Non implementa alcun test di uguaglianza (come l'override di Equals e GetHashCode), quindi NUnit alla fine eseguirà un confronto di riferimento. Ciò non riuscirà poiché ogni raccolta contiene diverse istanze di Example anche se i campi hanno gli stessi valori.

Si potrebbe risolvere questo aggiungendo quanto segue al ExampleClass

public override bool Equals(object o) { 
    var other = o as ExampleClass; 
    if (other == null) { return false; } 
    return this.Description == other.Description 
    && this.SKU == other.SKU 
    && this.Price == other.Price 
    && this.Qty == other.Qty; 
} 

public override int GetHashCode() { return 1; } 

Nota: ho scelto il valore 1 per GetHashCode perché questo è un tipo di mutevole e il valore di ritorno unico veramente sicuro per GetHashCode su un tipo mutabile è una costante Se intendi usarlo come chiave in un Dictionary<TKey,TValue>, ti consigliamo di rivisitare questo.

6

È necessario implementare Equals e GetHashCode sul ExampleClass. Senza di ciò, NUnit sta eseguendo un controllo di uguaglianza di riferimento ("sono questi esattamente lo stesso oggetto?"), Non un valore di uguaglianza uno ("questi oggetti si assomigliano?").

+2

L'implementazione equivale solo a scopi di test può introdurre Equality Pollution: http://xunitpatterns.com/Test%20Logic%20in%20Production.html#Equality Pollution –

+0

Ho corretto l'override di Equals e il mio test di esempio funziona. Quindi, è solo una buona pratica sovrascrivere il metodo GetHashCode() o è necessario per qualche altro motivo? Grazie! –

+1

L'implementazione 'GetHashCode' deve essere d'accordo con' Equals': se due oggetti sono uguali, devono avere lo stesso codice hash. (Due oggetti possono avere lo stesso codice hash anche se sono diversi, ma se oggetti diversi hanno lo stesso codice hash, 'Equals' deve restituire false.) –