Wie kann ich aus, die Kenntnisse über die Umsetzung Interna meine Unit-Tests verhindern, wenn Mock-Objekte verwenden?

StackOverflow https://stackoverflow.com/questions/3448121

Frage

Ich bin immer noch in den Lernstufen in Bezug auf Komponententests und insbesondere in Bezug auf spöttische (Ich verwende die PascalMock und DUnit Frameworks). Eine Sache, die ich stolperte jetzt war über, dass ich nicht einen Weg, um hart codierten Implementierungsdetails der getesteten Klasse / Schnittstelle in meinen Unit-Test finden konnte, und das fühlt sich einfach falsch ...

Zum Beispiel: Ich mag eine Klasse testen, dass Geräte eine sehr einfache Schnittstelle zum Lesen und Schreiben von Anwendungseinstellungen (im Grunde Namen / Wert-Paare). Die Schnittstelle, die den Verbraucher präsentiert wird, ist völlig agnostisch, wo und wie die Werte tatsächlich gespeichert sind (zum Beispiel Registry, INI-Datei, XML, Datenbank, etc.). Selbstverständlich ist die Zugriffsschicht durch noch eine andere Klasse implementiert, die in die Klasse getestet auf dem Bau injiziert werden. Ich habe ein Mock-Objekt für diese Zugriffsschicht, und ich bin jetzt in der Lage, die Schnittstelle-implementierende Klasse vollständig zu testen, ohne tatsächlich zu lesen oder zu einer Registry / INI-Datei zu schreiben alles / was auch immer.

Um jedoch die Mock verhält sich genau wie die reale Sache, um sicherzustellen, wenn sie von der getesteten Klasse zugegriffen wird, haben meine Unit-Tests das Mock-Objekt einzurichten durch sehr explizit erwartete Methodenaufrufe zu definieren und die Rückgabewerte der getesteten Klasse erwartet . Dies bedeutet, dass, wenn ich jemals Änderungen an der Schnittstelle der Zugriffsschicht oder auf dem Weg machen müssen, dass die getesteten Klasse verwendet diese Schicht I werden auch die Unit-Tests für die Klasse ändern müssen, dass intern die Schnittstelle verwendet, obwohl die < strong> Schnittstelle die Klasse I tatsächlich testen bin überhaupt nicht verändert hat. Ist das etwas, was ich will einfach mit leben müssen, wenn Mocks verwenden oder gibt es einen besseren Weg, um die Klasse-Abhängigkeiten zu gestalten, dass dies vermeiden würde?

War es hilfreich?

Lösung

  

Ist das etwas, werde ich nur haben,   leben mit bei der Verwendung von Mocks oder es ist   ein besserer Weg, das zu entwerfen   Klasse-Abhängigkeiten, die verhindern würden,   das?

Eine Menge Zeit verspottet (besonders sensible Frameworks wie JMock) zwingen Sie zu Konto für Details, die sich nicht direkt auf das Verhalten zu testen Sie versuchen, und manchmal kann dies auch hilfreich sein, von verdächtigem Code auszusetzen, das ist tun zu viel und hat zu viele Anrufe / Abhängigkeiten.

Doch in Ihrem Fall, wenn ich deine Beschreibung richtig gelesen, es klingt wie Sie nicht wirklich ein Problem haben. Wenn Sie die Lese- / Schreibschicht richtig gestalten und mit einem angemessenen Maß an Abstraktion, sollten Sie es nicht ändern müssen.

  

Das bedeutet, dass, wenn ich jemals haben   um Änderungen an der Schnittstelle von   die Zugangsschicht oder auf die Art und Weise, dass   die getestete Klasse verwendet diese Schicht I   muss auch das Gerät ändern   die Klasse testet für die intern   Anwendungen, die, obwohl die Schnittstelle   Schnittstelle der Klasse Ich bin eigentlich   Tests haben sich nicht verändert.

Ist das nicht der Punkt, der die abstrahierte Zugriffsschicht zu schreiben, dies zu vermeiden? In der Regel nach dem Offen / Geschlossen-Prinzip , eine Schnittstelle dieser Art nicht ändern und den Vertrag mit der Klasse nicht brechen soll, dass es verbraucht, und durch Erweiterung wird es auch nicht Komponententests durchbrechen. Nun, wenn Sie die Reihenfolge der Methodenaufrufe ändern, oder müssen neue Anrufe an die abstrahierten Schicht machen, dann, ja, vor allem mit einigen Frameworks, Ihre Mock Erwartungen brechen. Dies ist nur ein Teil der Kosten für die Nutzung spottet, und es ist durchaus akzeptabel. Aber die Schnittstelle selbst soll in der Regel stabil bleiben.

Andere Tipps

  

die Mock verhält sich genau wie die reale Sache zu gewährleisten, wenn der von dem geprüften Klasse zugegriffen, meine Unit-Tests das Mock-Objekt durch sehr explizit zu definieren erwartete Methodenaufrufe einzurichten haben und die Rückgabewerte der getesteten Klasse erwartet.

Richtig.

  

Änderungen an der Oberfläche der Zugriffsschicht oder auf die Art und Weise, dass die getesteten Klasse verwendet diese Schicht I werden auch die Unit-Tests ändern müssen

Richtig.

  

, obwohl die Schnittstelle der Klasse I tatsächlich testen bin hat überhaupt nicht verändert.

"Testen Eigentlich"? Sie meinen die Interface-Klasse ausgesetzt? Das ist gut.

Wie die „geprüft“ (Schnittstelle) Klasse verwendet, die Zugriffsschicht Mittel Sie die interne Schnittstelle zu der Zugriffsschicht geändert haben. Schnittstellenänderungen (auch interne sind) erfordern Test Änderungen und kann zum Bruch führen, wenn Sie etwas falsch gemacht haben.

Nichts falsch mit diesem. Tatsächlich ist der springende Punkt, dass jede Änderung der Zugriffsschicht muss erfordern Änderungen an den Mocks, um sicherzustellen, dass die Änderung „funktioniert“.

Die Prüfung wird nicht als „robust“ soll. Es soll spröde. Wenn Sie eine Änderung, dass Abspaltungen interne Verhalten machen, dann wird es können Pause. Wenn Ihre Tests zu robust wären, würden sie nicht Test nichts - sie würden nur Arbeit. Und das ist falsch.

Die Tests sollten nur für den exakt richtigen Grund arbeiten.

Nur einige Namen zu Ihrem Beispiel zu setzen,

  • RegistryBasedDictionary implementiert die Rolle (Schnittstelle) Wörterbuch.
  • RegistryBasedDictionary hat eine Abhängigkeit von der Rolle RegistryAccessor, implementiert durch RegistryWinAPIWrapper.

Sie daran interessiert sind zur Zeit in RegistryBasedDictionary testen. Die Einheit Tests würden eine mock Abhängigkeit für die RegistryAccessor Role injizieren und würde die erwartete Wechselwirkung mit den Abhängigkeiten testen.

  • Der Trick hier unnötige Test Wartung zu vermeiden, ist es, " Geben Sie genau, was passieren soll .. und nicht mehr ." (Aus das GOOS Buch (must-read für mock TDD gewürzt), so dass, wenn die Reihenfolge der Abhängigkeit Methodenaufrufe spielt keine Rolle, gebe es nicht in der Test bestanden. das lässt Sie die Reihenfolge der Anrufe bei der Umsetzung ändern befreien.)
  • Konstruktions die Rollen, so dass die sie enthalten keine Lecks von den tatsächlichen Implementierungen - halten die Rollen umsetzungs Agnostiker .

Der einzige Grund, RegistryBasedDictionary Tests zu ändern, wäre eine Änderung des Verhaltens von RegistryBasedDictionary sein und nicht in irgendeiner seiner Abhängigkeiten. Also, wenn seine Interaktion mit seinen Abhängigkeiten oder die Rollen / Verträge ändern, würden die Tests müssen aktualisiert werden, . Das ist der Preis für interaktionsbasierte Tests, die Sie zahlen müssen, für die Flexibilität Test in der Isolation. Doch in der Praxis ist es nicht, dass das oft geschehen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top