Ich habe einen Unit Test, der so aussieht:
[Test]
public void Should_create_person()
{
Assert.DoesNotThrow(() => new Person(Guid.NewGuid(), new DateTime(1972, 01, 01));
}
Ich behaupte, dass hier ein Personenobjekt erstellt wird, dh dass die Validierung nicht fehlschlägt. Wenn der Guid beispielsweise null ist oder das Geburtsdatum vor dem 01.01.1900 liegt, schlägt die Validierung fehl und eine Ausnahme wird ausgelöst (was bedeutet, dass der Test fehlschlägt).
Der Konstruktor sieht folgendermaßen aus:
public Person(Id id, DateTime dateOfBirth) :
base(id)
{
if (dateOfBirth == null)
throw new ArgumentNullException("Date of Birth");
elseif (dateOfBith < new DateTime(1900,01,01)
throw new ArgumentException("Date of Birth");
DateOfBirth = dateOfBirth;
}
Ist das eine gute Idee für einen Test?
Hinweis : Ich verfolge einen klassizistischen Ansatz zum Unit-Testen des Domänenmodells, wenn dies von Bedeutung ist.
c#
unit-testing
constructors
w0051977
quelle
quelle
Should_create_person
? Was soll eine Person schaffen? Geben Sie ihm einen aussagekräftigen Namen, wieCreating_person_with_valid_data_succeeds
.Antworten:
Dies ist ein gültiger Test (obwohl ziemlich übereifrig) und ich mache ihn manchmal, um die Konstruktorlogik zu testen. Wie Laiv in den Kommentaren erwähnt hat, sollten Sie sich jedoch fragen, warum.
Wenn Ihr Konstruktor so aussieht:
Ist es sinnvoll zu testen, ob es wirft? Ob die Parameter richtig zugewiesen sind, kann ich verstehen, aber Ihr Test ist ziemlich übertrieben.
Wenn Ihr Test jedoch ungefähr so funktioniert:
Dann wird Ihr Test relevanter (da Sie tatsächlich irgendwo im Code Ausnahmen auslösen).
Eine Sache würde ich sagen, im Allgemeinen ist es eine schlechte Praxis, viel Logik in Ihrem Konstruktor zu haben. Die grundlegende Validierung (wie die oben durchgeführten Null- / Standardprüfungen) ist in Ordnung. Aber wenn Sie eine Verbindung zu Datenbanken herstellen und Daten von jemandem laden, riecht Code dort wirklich ...
Wenn Ihr Konstruktor es wert ist, getestet zu werden (weil viel Logik vorhanden ist), stimmt aus diesem Grund möglicherweise etwas anderes nicht.
Sie werden mit ziemlicher Sicherheit andere Tests haben, die diese Klasse in Geschäftslogikebenen abdecken. Konstruktoren und Variablenzuweisungen werden mit ziemlicher Sicherheit eine vollständige Abdeckung durch diese Tests erhalten. Daher ist es möglicherweise sinnlos, spezifische Tests speziell für den Konstruktor hinzuzufügen. Nichts ist jedoch schwarzweiß und ich hätte nichts gegen diese Tests, wenn ich sie mit Code überprüfen würde - aber ich würde fragen, ob sie über die Tests an anderer Stelle in Ihrer Lösung hinaus einen Mehrwert bieten.
In Ihrem Beispiel:
Sie führen nicht nur eine Validierung durch, sondern rufen auch einen Basiskonstruktor auf. Für mich ist dies ein weiterer Grund für diese Tests, da die Konstruktor- / Validierungslogik jetzt auf zwei Klassen aufgeteilt ist, was die Sichtbarkeit verringert und das Risiko unerwarteter Änderungen erhöht.
TLDR
Diese Tests haben einen gewissen Wert, die Validierungs- / Zuweisungslogik wird jedoch wahrscheinlich von anderen Tests in Ihrer Lösung abgedeckt. Wenn diese Konstruktoren viel Logik enthalten, die erhebliche Tests erfordert, deutet dies darauf hin, dass dort ein unangenehmer Codegeruch lauert.
quelle
PersonBirthdate
), der die Validierung des Geburtsdatums durchführt. Ebenso könnte dieGuid
Prüfung für dieId
Klasse implementiert werden . Dies bedeutet, dass Sie diese Validierungslogik wirklich nicht mehr imPerson
Konstruktor haben müssen, da es nicht möglich ist, eine mit ungültigen Daten zu konstruieren - außer fürnull
refs. Natürlich müssen Sie Tests für die anderen beiden Klassen schreiben :)Hier schon eine gute Antwort, aber ich denke, eine weitere Sache ist erwähnenswert.
Wenn man TDD "by the book" macht, muss man zuerst einen Test schreiben, der den Konstruktor aufruft, noch bevor der Konstruktor implementiert wird. Dieser Test könnte tatsächlich so aussehen wie der von Ihnen vorgestellte, selbst wenn die Implementierung des Konstruktors keine Validierungslogik enthält.
Beachten Sie auch, dass man für TDD zuerst einen anderen Test wie schreiben sollte
bevor Sie die Prüfung für
DateTime(1900,01,01)
zum Konstruktor hinzufügen .Im TDD-Kontext ist der gezeigte Test durchaus sinnvoll.
quelle