2010-01-12 10 views
11

Mein Entwicklungsteam hat begonnen, Mockito zu verwenden und Klassen zu verwenden, die als 'final' definiert wurden. Ich habe in Effektivem Java von Joshua Bloch und im SO-Thread When to use final gelesen, dass alle Klassen den letzten Modifikator verwenden sollten. Es gab Meinungsverschiedenheiten im Thread, aber ich stimme der Idee zu, die Klassenzusammensetzung zu erzwingen, wenn die Vererbung keinen Sinn ergibt.Was ist zu tun, wenn Java Best Practices mit Mockito kollidieren?

Was soll ich tun, wenn ich Klassen mit einem Testframework wie Mockito testen möchte, das erfordert, dass Klassen nicht den 'finalen' Modifikator haben? Ich hoffe, dass jemand anderes während seiner Entwicklung auf ähnliche Probleme gestoßen ist. Zu welchen Vorsätzen kam Ihr Entwicklungsteam?

Es gibt zwei offensichtliche Antworten wie die Verwendung von JMock oder den 'finalen' Modifikator für die Klassen, die wir testen möchten, aber wir wollen mit einem externen Testframework (neben JUnit) bleiben und es kann schwierig sein, andere zu überzeugen Entwickler, um den 'finalen' Modifikator zu entfernen.

Danke.

+4

Es ist sicherlich keine bewährte Methode, alle * Klassen * 'final' zu erstellen. Es ist schon eine Weile her, seit ich Effektives Java gelesen habe, aber der Konsens des verknüpften Threads scheint dies auch nicht zu implizieren. Sie sollten die Klassen "final" markieren, um zu signalisieren, dass sie aus irgendeinem Grund nicht erweitert werden sollten - wenn es keinen Grund gibt, fügt sie einfach unnötige Komplexität hinzu - wie Sie gefunden haben. Wenn Sie bemerken, dass Sie die Klasse irgendwo weiter ausbauen müssen, müssen Sie den Code der ursprünglichen Klasse ändern, um die neue Klasse zu schreiben - was gegen das Open/Closed-Prinzip verstößt. – Nate

Antwort

10

Was brauchen Sie am meisten:

  1. Die Fähigkeit, sicher zu stellen, dass jemand nicht von Ihrer Klasse erbt, OR
  2. Die Fähigkeit, sicher zu stellen, dass Ihr Code testbar ist Ihr Mockframework der Verwendung Wahl?

Generell glaube ich, dass Sie nicht erzwingen müssen (1). Für mich ist Testbarkeit (2) viel wichtiger. Was passt am besten zu deiner Situation?

+0

Testbarkeit ist viel wichtiger IMHO und ich glaube, es passt zu unserer Situation. – austen

+1

Es gibt keine Notwendigkeit, Design aus Gründen der "Testbarkeit" zu opfern. Sie können beides haben, indem Sie einfach das richtige Werkzeug für den Job verwenden.Verwenden Sie in diesem Fall eines der Java-Mockingtools, mit dem Sie finale Methoden und Klassen ausprobieren können: JMockit (mein eigenes Tool) oder PowerMock (das die Mockito-API unterstützt, sodass Sie vorhandene Tests nicht vollständig neu schreiben müssen). –

4

Wenn Sie möchten, dass Ihre Klassen endgültig sind, können Sie Schnittstellen implementieren lassen. Die Schnittstellen sind mockbar.

4

Wie bereits in der anderen Antwort erwähnt, können Sie Ihre letzten Klassen implementieren Schnittstelle (n) implementieren und in Ihren Tests die Schnittstelle (n) verspotten.

Dies ist einer der Vorteile der Verwendung von Mock-Objekten; In Szenarien wie diesem können Sie darüber nachdenken, wie der Code besser organisiert werden kann. Wenn Ihre Codebasis viel Bezug zu finalen Klassen hat (also an konkrete Implementierung bindet), verstößt sie gegen das OO-Prinzip "Programmierung an eine Schnittstelle" und die Notwendigkeit besserer Testbarkeit würde Ihnen helfen, über Refactoring nachzudenken, um die Abhängigkeit von konkreten Implementierungen zu eliminieren.

Dieses Papier auf Verwendung von Mock-Objekte Endo-testing: Unit Testing with Mock Objects einen Abschnitt (4.4) Schnittstelle Entdeckung, die erklärt, wie Mock-Objekte helfen bei der Entdeckung der Schnittstellen betitelt hat.

+0

Ich mag die Idee der Schnittstellenerkennung. – austen

+3

Wenn ich Code schreibe, der eine letzte Klasse verwendet und diese Klasse keine separate Schnittstelle implementiert, verstoße ich * nicht * gegen das "Programm zu einer Schnittstelle, nicht eine Implementierung" GoF-Prinzip. Das Prinzip erfordert * nicht *, dass jede Klasse eine separate Schnittstelle implementiert. Andere Teile des GoF-Buches machen dies klar, für diejenigen, die es tatsächlich lesen wollen. –