2012-10-22 8 views
9
[Test] 
public void testMultiplication() 
{ 
    var five=new Dollar(5); 
    Assert.AreEqual(new Dollar(10), five.times(2)); 
    Assert.AreEqual(new Dollar(15), five.times(3)); 
} 

Dollar KlasseNUnit Test Fehler? Erwartet <MyType> Aber war <MyType>

public class Dollar 
{ 
    private int amount; 

    public Dollar(int amount) 
    { 
     this.amount = amount; 
    } 

    public Dollar times(int multiplier) 
    { 
     return new Dollar(amount * multiplier); 
    } 

    public bool equals(Object theObject) 
    { 
     Dollar dollar = (Dollar) theObject; 

     return amount == dollar.amount; 
    } 
} 

On line Assert.AreEqual (neu Dollar (10), five.times (2)); Test nicht mit Fehlern:

Erwartet: TDDbooks.Dollar

Aber war: TDDbooks.Dollar

+0

beiseite: warum implementieren Sie nicht Operator Overloading? –

+0

Sieht so aus, als könnte es sich um ein Assembly-Versionierungsproblem handeln. ist es möglich, dass Sie zwei Versionen der Assembly haben, die 'TDDbooks.Dollar' geladen implementiert? –

Antwort

4

NUnit zeigt die Zeichenfolgendarstellung von Objekten an. Um handliche Ausgabe zu haben, sollten Sie ToString Methode der Dollar Klasse außer Kraft setzen:

public override string ToString() 
{ 
    return "$" + amount; 
} 

Jetzt Ausgabe aussehen wird:

Expected: $10 
But was: $10 

Nächstes Problem Dollar Vergleich ist. NUnit vergleichen Objekte durch Aufruf Equals Methode (nicht equals, aber Equals. Kent Beck verwendet Java in seinen Beispielen. In C# haben wir Pascal Namen für Methoden). Die Standardimplementierung der Methode Equals gibt true zurück, wenn Objekte dieselbe Referenz haben. Aber in Times Methode erstellen Sie neue Instanz von Dollar Klasse. Um das zu beheben, sollten Sie die Methodenimplementierung Equals ändern, um das Betragsfeld zu vergleichen.

public override bool Equals(object obj) 
{ 
    Dollar other = obj as Dollar; 
    if (other == null) 
    return false; 

    return amount == other.amount; 
} 

Beachten Sie auch, dass Sie override Schlüsselwort für übergeordnete Basisklasse Funktionalität verwenden soll. Und noch eine Sache - wenn Sie Equals Funktionalität überschreiben, sollten Sie GetHashCode Methode überschreiben. In Ihrem Fall ist es OK, etwas zu haben, wie:

public override int GetHashCode() 
{ 
    return amount.GetHashCode(); 
} 
+2

Wenn Sie nicht aus der Klasse "Dollar" ableiten möchten, sollten Sie auch "versiegelt" wählen. Wenn Sie es nicht "versiegelt" machen, denken Sie darüber nach, if (GetType()! = Other.GetType()) return false; 'innerhalb der Equals-Methode anzugeben. Andernfalls könnten Sie ein schlechtes Ergebnis erhalten, wenn "anderes" ein "Dollar" eines abgeleiteten Typs ist, wie beispielsweise ein 'DescriptionDollar'. –

11

Die Assert.AreEquals Methode wird die Equals Methode Gleichheit zu testen. Anstatt Object.Equals zu überschreiben, definiert der Dollar-Typ nur eine neue equals-Methode, die nicht an der .Net-Objektgleichheit beteiligt ist. Daher wird es nicht verwendet und der Test verwendet die Referenzgleichheit, die fehlschlägt. Um dies zu beheben Sie die Object.Equals Methode überschreiben, müssen

public override bool Equals(object obj) { 
    Dollar other = obj as Dollar; 
    if (other == null) { 
    return false; 
    } 

    return amount == other.amount; 
} 
0

Es gibt ein paar Dinge:

  1. Sie definiert haben eine neue Methode equals, statt Überschreiben der Basisklassenmethode Equals. Wechseln Sie zum Überschreiben und NUnit ruft Ihre Methode auf.
  2. NUnit druckt das Objekt mit seiner ToString aus, und die Standardimplementierung von ToString besteht darin, einfach den Klassennamen auszugeben. Überschreiben Sie ToString, um die Menge zu drucken, und die Assertion-Nachricht wird viel mehr Sinn machen.
0

Was du da behaupten, dass new Dollar(10) ist das gleiche Objekt wie die five.times(2) zurückkehrt, was nicht wahr ist.

Wenn Sie auf diese Weise behaupten wollen, würden Sie die Equals-Methode in Ihrem Dollar Klasse wie folgt überlasten müssen:

public override bool Equals(Object obj) 
{ 
    if (obj is Dollar) 
    { 
     return this.Amount == ((Dollar)obj).Amount; 
    } 
    return false; 
} 

Sie sind nicht das override Schlüsselwort in Ihrer Equals Methode.

0

Die beste Lösung wurde bereits von einigen Leuten gegeben, aber es gibt eine Alternative, die in anderen Situationen funktionieren könnte. Sie müssten einen Getter für das amount Feld hinzufügen wie folgt:

public int Amount { get { return amount; } } 

Und dann, wenn Sie das Gerät zu testen tun, würde es wie folgt aussehen:

Assert.AreEqual(10, five.times(2).Amount); 

So, jetzt sind Vergleichen Sie ein int zu einem anderen int. Alternativ könnten Sie die amount Variable öffentlich machen, obwohl das die Kapselung bricht. Offensichtlich ist die Verwendung der Equals Methode in diesem Fall der bessere Weg, aber in manchen Situationen ist dies möglicherweise vorzuziehen.

Verwandte Themen