Código Java testeable

Introducción

Hace un tiempo, después de leer en casa sobre test unitarios y de haber hecho bastantes ejercicios, decidí escribir test unitarios en el trabajo.

La idea era escribir los test unitarios después de escribir el código de producción.
Nota: En varios libros y artículos comentan que la mejor forma de comenzar a escribir test unitarios en el trabajo es cuando surjan incidencias o problemas y creo que tienen razón. Si lo hubiera hecho así hubiera sido más fácil 🙂

Tras varios intentos fallidos me encontraba realmente frustrado: ¿porqué me resultaba tan complicado escribir test unitarios si en mi casa no tenía ningún problema?

Entonces llegué a un artículo de Michael Feathers donde aparece la siguiente frase en el primer párrafo:

Code that wasn't designed to be testable is not testable. Testability is not a quality that appears accidently. Or does it?

Código que no ha sido diseñado para ser testeable no es testeable. La testeabilidad no es cualidad que aparece accidentalmente. ¿O si?

Entonces, me dí cuenta que me resultaba tan complicado escribir test unitarios porque mi código no era testeable.
Este hallazgo fue a la vez una liberación y un palo porque a quién le gusta saber que su código no está diseñado de forma adecuada.

 

Código Java testeable

Si os habéis leído el artículo, poco más os puedo contar. Bueno, puedo contaros mi versión del artículo porque personalmente me resulta complicado el acordarme de todos los sitios en los no tengo que que estar pendiente donde pongo código TUF (Test Unfriendly Feature).

Así, para escribir código testeable hay que seguir los siguiente consejos:

  1. No escribas métodos estáticos o bloques de código estático.
  2. No escribas clases finales ni métodos finales
  3. Inyecta en tu código los colaboradores de la clase a testear (principalmente las que “hablan” con la base de datos, internet, sistema de ficheros o interfaz de usuario) y añádelas como atributos. Escribí un artículo sobre la inyección de dependencias en http://www.enrique-martin.com/2014/05/injeccion-de-dependencias-en-java-para.html
  4. Inyecta interfaces en lugar de clases. Es mejor depender de abstracciones que de implementaciones. Además creo que tiene sentido porque ¿para qué queremos inyectar una clase concreta si lo que queremos es que nuestro código sea más flexible?

Si practicas los dos primeros puntos tu código va a mejorar mucho en testeabilidad. En cuanto a los puntos 3 y 4 difieren a lo que aparece en el artículo.

Creo que si sigues los puntos 3 y 4 la mayoría de los problemas que se comentan en el artículos, como son en la clases privadas y en los constructores, se solucionan.

 

Porqué

Como pone en el artículo, todos los consejos están relacionados con la forma en que se escriben test unitarios.
Un test unitario debe ser rápido y repetible y suelen no cumplirse estas propiedades si, por ejemplo, se accede a base de datos en el código.
Así, lo que se hace es crear una subclase de la clase donde está el problema y se sobrescribe el método para que se comporte como queramos. Si no se puede sobreescribir el método resulta muy complicado el testearlo.

Por ejemplo, si queremos que un método devuelva siempre una lista vacía, y este método es estático. No podremos sobreescribirlo en la subclase, y por lo tanto no podemos hacer que se comporte como queremos.

En conclusión, si tu código no tiene test unitarios seguramente tú código no es testeable por lo que te va a resultar complicado escribir test unitarios.