2010-01-12 12 views
11

Mi equipo de desarrollo ha comenzado a utilizar Mockito y tiene clases que se han definido como 'final'. He leído en Java efectivo por Joshua Bloch y en el hilo SO When to use final que todas las clases deben usar el modificador final. Ha habido algún desacuerdo en el hilo, pero estoy de acuerdo con la idea de forzar la composición de la clase a menos que la herencia tenga sentido.Qué hacer cuando las prácticas recomendadas de Java entran en conflicto con Mockito

¿Qué debo hacer cuando quiero probar clases usando un marco de prueba como Mockito que requiere que las clases no tengan el modificador "final"? Espero que alguien más haya tenido problemas similares durante su desarrollo. ¿A qué resoluciones llegó su equipo de desarrollo?

Hay dos respuestas obvias como usar JMock o eliminar el modificador 'final' en las clases que queremos probar, pero queremos seguir con un marco de prueba externo (además de JUnit) y puede ser difícil convencer a otros desarrolladores para eliminar el modificador 'final'.

Gracias.

+4

Hacer todas las * clases * 'final' ciertamente no es una buena práctica ... ha pasado un tiempo desde la lectura de Java efectivo, pero el consenso del hilo vinculado ciertamente tampoco parece implicar eso. Debe marcar las clases 'final' para indicar que hay alguna razón por la que no deberían extenderse, si no hay motivo, simplemente agrega una complejidad innecesaria, como ha descubierto. Además, si se da cuenta de que necesita extender la clase en algún momento, tiene que cambiar el código de la clase original para escribir la nueva clase, violando el principio Abierto/Cerrado. – Nate

Respuesta

10

¿Qué es lo que más necesitan:

  1. La capacidad para asegurarse de que alguien no hereda de su clase o
  2. La capacidad para asegurarse de que su código es comprobable mediante su marco de burla de ¿elección?

Generalmente, creo que no es necesario hacer cumplir (1). Para mí, la capacidad de prueba (2) es mucho más importante. ¿Qué se adapta mejor a tu situación?

+0

La capacidad de prueba es mucho más importante en mi humilde opinión y creo que se ajusta a nuestra situación. – austen

+1

No hay necesidad de sacrificar el diseño por el bien de la "capacidad de prueba". Puede tener ambos, simplemente usando la herramienta correcta para el trabajo.En este caso, utilice una de las herramientas de simulación de Java que pueden simular los métodos y clases finales: JMockit (mi propia herramienta) o PowerMock (que admite la API de Mockito, por lo que no tiene que volver a escribir completamente las pruebas existentes). –

4

Si desea que sus clases sean definitivas, puede hacer que implementen las interfaces. Las interfaces son burlables.

4

Como ya se mencionó en la otra respuesta, puede hacer que sus clases finales implementen las interfaces y en sus pruebas se burlan de la (s) interfaz (es).

Este es uno de los beneficios de usar objetos Mock; en escenarios como este te hacen pensar cómo se puede organizar mejor el código. Si su base de código tiene mucha referencia a clases finales (por lo tanto vinculante para la implementación concreta) viola el principio OO de "programación a una interfaz" y la necesidad de una mejor capacidad de prueba lo ayudará a pensar en refactorizar para eliminar la dependencia en implementaciones concretas.

Este papel en el uso de Mock Objetos Endo-testing: Unit Testing with Mock Objects tiene una sección (4.4) titulado descubrimiento Interface que explica cómo mock objetos ayudan en el descubrimiento de los interfaces.

+0

Me gusta la idea del descubrimiento de interfaz. – austen

+3

Cuando escribo código que usa una clase final y esta clase no implementa una interfaz separada, * no * estoy violando el principio de GoF del "programa para una interfaz, no una implementación". El principio * no * requiere que cada clase implemente una interfaz separada. Otras partes del libro de GoF lo dejan claro, para aquellos dispuestos a leerlo realmente. –

Cuestiones relacionadas