Ich arbeite durch Kent Becks TDD mit Beispiel als eine akademische Übung, aber mit MSpec, um die Tests zu schreiben. Wenn ich bearbeiteten Beispielen folge, möchte ich eine Wendung einführen, damit ich den Text nicht einfach kopieren kann. Ich finde, dass ich dazu tendiere, auf Probleme zu stoßen, die ich lösen muss, und am Ende viel mehr lerne. Ich glaube, das ist eine dieser Gelegenheiten.Warum wird meine Equals-Methode nicht aufgerufen?
Ich bin ein Stück weit durch Kents 'Geld' Beispiel. Hier ist die Klassenstruktur ich habe:
Ich habe die folgenden zwei Test Kontexten:
[Subject(typeof(Money), "Equality")]
public class when_comparing_different_classes_for_equality
{
Because of =() => FiveFrancs = new Franc(5, "CHF");
It should_equal_money_with_currency_set_to_francs =() => FiveFrancs.Equals(new Money(5, "CHF")).ShouldBeTrue();
static Franc FiveFrancs;
}
[Subject(typeof(Franc), "multiplication")]
public class when_multiplying_a_franc_amount_by_an_integer
{
Because of =() => FiveFrancs = new Franc(5, null);
It should_be_ten_francs_when_multiplied_by_2 =() => FiveFrancs.Times(2).ShouldEqual(Money.Franc(10));
It should_be_fifteen_francs_when_multiplied_by_3 =() => FiveFrancs.Times(3).ShouldEqual(Money.Franc(15));
static Franc FiveFrancs;
}
The Times() Methode gibt ein neues Objekt vom Typ Geld das Ergebnis enthält, das heißt, die Objekte sind unveränderlich. Der erste obige Kontext wird übergeben, was darauf hindeutet, dass Equals wie erwartet funktioniert, d. h. es ignoriert die Objekttypen, solange sie beide von Money geerbt werden und vergleicht nur, dass Betrag und Währungsfelder gleich sind. Der zweite Kontext schlägt bei einer ähnlichen Ausgabe fehl:
Machine.Specifications.SpecificationException
Expected: TDDByExample.Money.Specifications.Franc:[15]
But was: TDDByExample.Money.Specifications.Money:[15]
at TDDByExample.Money.Specifications.when_multiplying_a_franc_amount_by_an_integer.<.ctor>b__2() in MoneySpecs.cs: line 29
Gleichheit ist definiert als Menge (Wert) und Währung, die gleich sind; Der tatsächliche Typ des Objekts wird ignoriert. Das beabsichtigte Ergebnis ist also, dass es egal ist, ob ich die Gleichheit mit Money- oder Franc-Objekten teste, solange die Betrags- und Währungsfelder gleich sind. Die Dinge funktionieren jedoch nicht wie geplant. Beim Debuggen werden meine Equals() -Methoden nicht einmal aufgerufen. Da ist eindeutig etwas, was ich hier nicht verstehe. Ich bin mir sicher, dass die Lösung blendend offensichtlich wird, wenn ich es weiß, aber ich kann es nicht sehen. Kann mir jemand einen Vorschlag machen, was ich tun muss, damit das funktioniert?
Hier ist die Implementierung von Equals():
public bool Equals(Money other)
{
return amount == other.amount && currency == other.currency;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
return false;
if (ReferenceEquals(this, obj))
return true;
return Equals(obj as Money);
}
Nach viel Überlegung glaube ich, dass dies ein MSpec Problem sein kann. MSpec vergleicht die Objekttypen und vergleicht den Vergleich nicht, weil die Typen nicht übereinstimmen. Nur wenn die Typen gleich sind, verwendet MSpec dann einen wertebasierten Vergleich. Das ist der Grund, warum meine Equals-Methode nie aufgerufen wird. Ich glaube jedoch, dass Liskov sagt, dass ich in der Lage sein sollte, ein Geld mit einem Franc zu vergleichen, wenn meine Definition von Gleichheit dies zulässt.Daher habe ich ein Problem mit dem MSpec-Projekt geöffnet. https://github.com/machine/machine.specifications/issues/200 –
@Anthony Ich bevorzuge Whitesmiths Stil Einrückung (geschweifte Klammern eingerückt). Es macht mir nichts aus, wenn Sie meine Einrückung ändern, und ich bin froh, dass Ihre Änderungen bestehen bleiben, aber auf der anderen Seite scheint es etwas vermessen zu sein, die Vorlieben anderer Menschen zu übersteuern. Gibt es eine Richtlinie, die mir nicht bekannt ist? –
Oh, tut mir leid, ich habe einfach nur angenommen, dass du einen schlechten Platz/Tab Mix hast oder so. Ich bekomme glänzende Augen von der allgemeinen schlechten Code-Block-Formatierung von SO. –