2008-09-19 9 views
5

Wenn Sie Komposition verwenden, können Sie die anderen Objekte , von denen Ihre geprüfte Klasse abhängt, spotten, aber wenn Sie Vererbung verwenden, können Sie die Basisklasse nicht mocksen. (? Oder können Sie)Wie erteile ich Unit-Test erben Objekte?

Ich versuche im Allgemeinen prefer composition over inheritance, aber manchmal Vererbung scheint wirklich wie das beste Werkzeug für den Job - na ja, zumindest bis es zu Komponententests kommt.

Also, wie testen Sie die Vererbung? Oder trashst du es einfach als untestable und verwendest stattdessen die Komposition?

Hinweis: Ich benutze meistens PHP und PHPUnit, so Hilfe auf dieser Seite wird am meisten geschätzt. Aber es wäre auch interessant zu wissen, , wenn es Lösungen für dieses Problem in anderen Sprachen gibt.

+0

Es gibt ein [nettes Beispiel] (http://stackoverflow.com/questions/58969/best-way-to-unit-test-a-website-with-multiple-user-types-with-phpunit#63442) für [die Lösung von munificent gegeben] (http://stackoverflow.com/questions/100795/how-doi-iunit-test-inheriting-objects#116340). Lassen Sie die Testhierarchie Ihrer Klassenhierarchie ähneln. – GrGr

+0

Ich sehe nicht, wie es möglich wäre, eine Superklasse zu verspotten. Das müsste ein Sprachfeature sein. Was genau versuchst du zu testen? Für mich klingt das nach Reflektion könnte dir helfen? – Robse

+0

Ich weiß auch nicht, wie eine Elternklasse zu verspotten wäre. Deshalb frage ich. Aber ich denke nicht, dass es unmöglich ist - sehr wenige Dinge in Computern sind. –

Antwort

4

Solange Sie öffentliche Methoden der übergeordneten Klasse nicht überschreiben, sehe ich nicht, warum Sie sie auf allen Unterklassen davon testen müssen. Unit testet die Methoden für die Elternklasse und testet nur die neuen Methoden oder die überschriebenen für die Unterklassen.

1

Warum sollten Sie die Basisklasse verspotten?

Wie können Sie abgeleitete Klassen aus einer nicht vorhandenen Elternklasse erstellen?

Testen Sie es einfach wie gewohnt, aber haben Sie die Elternklasse.

Ich denke, Sie haben nicht die ganze Geschichte erzählt.

Außerdem funktionieren die Sprachfunktionen angeblich (es sei denn, Sie arbeiten mit Beta-Versionen oder so), so dass Sie nicht testen müssen, ob die Methode tatsächlich in einer abgeleiteten Klasse existiert.

3

Der Grund, warum Sie Mock-Objekte in Komposition verwenden, ist, wenn die realen Objekte etwas tun, das Sie nicht einrichten möchten (wie Sockets verwenden, serielle Ports, Benutzereingaben erhalten, sperrige Daten abrufen usw.). Sie sollten immer echte Objekte verwenden, wo es möglich ist. Mock-Objekte sind nur dann verfügbar, wenn der geschätzte Aufwand zum Implementieren und Verwalten eines Tests unter Verwendung eines realen Objekts größer ist als der zum Implementieren und Aufrechterhalten eines Tests unter Verwendung eines Mock-Objekts. Deine Basisklasse sollte nichts Besonderes machen!

Sie müssen also nicht die Vererbung testen. Vermutlich verwenden Sie das Verhalten der Basisklasse. Testen Sie die abgeleitete Klasse also so, wie Sie es normalerweise tun würden - indem Sie Methoden sowohl für die Basisklasse als auch für die abgeleitete Klasse aufrufen, die für den Test geeignet sind. Dies stellt sicher, dass das gesamte beabsichtigte Verhalten der abgeleiteten Klasse getestet wird.

Im Wesentlichen (meist) testen Sie eine abgeleitete Klasse so, als ob die Basisklasse unsichtbar wäre.

0

Nein, Sie nicht. Sie müssen nur überprüfen, ob die überschriebenen Methoden das tun, was sie sollten. Es sollte auf keinen Fall das Verhalten Ihrer Elternmethoden beeinflussen. Wenn Ihre übergeordneten Methoden fehlschlagen, bedeutet dies, dass Sie gebundene Bedingungen beim Testen auf der übergeordneten Ebene nicht erfüllt haben.

+0

Sie haben recht, und genau darauf ziele ich auch! Solange Sie eine Methode in einer Unterklasse außer Kraft setzen, MÜSSEN Sie diese Einheit testen. Die Tatsache, dass es die übergeordnete Methode aufruft oder nicht, spielt keine Rolle. Testen Sie einfach, dass das Ergebnis der Methode der Unterklasse das ist, was Sie erwarten, und dass die übergeordnete Methode sich so verhält, wie Sie es wollen. Darüber hinaus gibt es, wie @metao gezeigt hat, in Ihrer Elternklasse keine zusätzliche Statuseinstellung, die Sie in Ihrer Unterklasse nicht gefunden haben. Und wenn dies der Fall ist, sollten Sie die Verwendung der Komposition über die Vererbung neu überdenken. – gizmo

+0

Ich stimme völlig zu, dass die Methoden der Unterklasse nicht die Art beeinflussen sollten, wie sich Elternklassenmethoden verhalten. Deshalb habe ich vermeiden Zugriff auf Member-Variablen der Elternklasse und nur seine öffentlichen Schnittstelle verwendet. Aber wenn die Unterklassenmethode die Methode in der Elternklasse aufruft, dann wenn ich die Unterklassenmethode testet, leite ich auch die Elternklassenmethode ab. –

5

Verwenden Sie eine Reihe von Komponententests, die die Klassenhierarchie widerspiegeln. Wenn Sie eine Basisklasse Base und eine abgeleitete Klasse Derived haben, dann haben Sie Testklassen BaseTests und werden von diesen DerivedTests abgeleitet. BaseTests ist dafür verantwortlich, alles zu testen, was in Base definiert ist. DerivedTests erbt diese Tests und ist auch dafür verantwortlich, alles in Derived zu testen.

Wenn Sie die geschützten virtuellen Methoden in Base (d. H. Die Schnittstelle zwischen Base und seinen abgeleiteten Klassen) testen möchten, kann es auch sinnvoll sein, eine testbasierte Klasse zu erstellen, die diese Schnittstelle testet.