tutorial power mock example compatible and java unit-testing design dependency-injection junit

java - example - powermock maven



Usando PowerMock o ¿Cuánto permite que sus pruebas afecten su diseño? (6)

Creo que tienes razón para preocuparte. Refactorizar el código heredado para que sea comprobable no es tan difícil en la mayoría de los casos una vez que haya aprendido cómo hacerlo.

Mejor ir un poco más lento y tener un ambiente de apoyo para el aprendizaje que tomar un atajo y aprender malos hábitos.

(Y acabo de leer esto y siento que es relevante).

He sido fanático de EasyMock durante muchos años y, gracias a SO, me encontré con referencias a PowerMock y su capacidad de simular constructores y métodos estáticos, los cuales causan problemas al volver a instalar las pruebas en una base de código heredada.

Obviamente, uno de los enormes beneficios de las pruebas unitarias (y TDD) es la forma en que conduce a (¿fuerzas?) Un diseño mucho más limpio, y me parece que la introducción de PowerMock puede restar valor a eso. Vería esto principalmente manifestándose como:

  1. Volviendo a inicializar colaboradores en lugar de inyectarlos
  2. Usar estática en lugar de hacer que el método sea propiedad de un colaborador

Además de esto, algo no me sienta bien sobre mi código manipulado por bytecode para la prueba. Realmente no puedo dar una razón concreta para esto, solo que me hace sentir un poco incómodo ya que es solo para la prueba y no para la producción.

En mi concierto actual, estamos presionando para que las pruebas unitarias sean una forma de que las personas mejoren sus prácticas de codificación y se siente como si introducir PowerMock en la ecuación pudiera permitir que las personas saltaran ese paso un poco y estoy reacia a comenzar a usarlo. Habiendo dicho eso, realmente puedo ver dónde usarlo puede reducir la cantidad de refactorización que se necesita para comenzar a probar una clase.

Supongo que mi pregunta es, ¿cuáles son las experiencias de las personas al usar PowerMock (o cualquier otra biblioteca similar) para estas características, las usarías y en general, ¿quieres que tus pruebas influyan en tu diseño?


Creo que tienes razón; si necesitas PowerMock, probablemente tengas un código maloliente. Deshazte de esas estáticas.

Sin embargo, creo que estás equivocado sobre la instrumentación de bytecode. Me burlo de las clases concretas todo el tiempo usando mockito , me evita tener que escribir una interfaz para cada cosa . soltero. clase . Eso es mucho más limpio.

Solo tú puedes evitar los olores del código.


Hemos tenido muchas de las mismas preguntas que surgen en .NET arena, con respecto a Typemock Isolator. Ver esta publicación en el blog

Creo que cuando las personas comiencen a darse cuenta de que la Testabilidad no es un objetivo final, y que el diseño se aprende de otras maneras, dejaremos de dejar que nuestro miedo dicte qué herramientas usamos, o no usaremos una tecnología más avanzada cuando y si se vuelve pertinente.

Además, tiene sentido poder elegir la forma de diseñar, según las necesidades de la aplicación. no dejes que una herramienta te diga cómo diseñar, no te dejará otra opción.

(Trabajo en Typemock, pero una vez estuve en contra)


Estoy totalmente de acuerdo en que la capacidad de prueba no es un objetivo final, esta ha sido una de las cosas que me he dado cuenta al desarrollar PowerMock. También estoy de acuerdo en que escribir pruebas unitarias es una forma de obtener un buen diseño. El uso de PowerMock probablemente sea una excepción en lugar de una regla, al menos funciones como expectativas en constructores y burlas estáticas.

La motivación principal que tenemos para usar PowerMock es cuando utilizamos un código de un tercero que impide que su código sea comprobable. Una buena alternativa es utilizar una capa anticorrupción que abstraiga el código de terceros y lo haga comprobable. Sin embargo, a veces creo que el código es más limpio simplemente usando las API estándar. Un buen ejemplo de esto es la API de Java ME. Esto está lleno de llamadas a métodos estáticos que evitan las pruebas unitarias.

El mismo problema puede ocurrir con el código heredado. Algunas organizaciones tienen mucho miedo de modificar su código existente y, en este caso, PowerMock se puede utilizar para introducir pruebas unitarias en las partes que está escribiendo en este momento, sin forzar grandes refactorizaciones.

Nuestro problema es especificar un conjunto de reglas de mejores prácticas para usar PowerMock o no que un desarrollador novato pueda seguir. Crear un buen diseño es realmente difícil y, dado que PowerMock te ofrece más opciones, ¿tal vez solo sea más difícil para un principiante? Creo que un desarrollador más experimentado aprecia tener más opciones.

(fundador de PowerMock )


Tengo que estar totalmente en desacuerdo con esta pregunta.

No hay justificación para una herramienta de burla que limita las opciones de diseño. No son sólo los métodos estáticos los que EasyMock, EasyMock Class Extension, jMock, Mockito y otros eliminan. Estas herramientas también le impiden declarar clases y métodos final , y eso solo es algo muy malo. (Si necesita una fuente autorizada que defienda el uso de las clases y los métodos final , consulte el libro "Java efectivo" o vea esta presentación del autor).

Y "inicializar colaboradores en lugar de inyectarlos" a menudo es el mejor diseño, en mi experiencia. Si descompone una clase que resuelve algún problema complejo mediante la creación de clases auxiliares que se crean instancias de esa clase, puede aprovechar la capacidad de pasar datos específicos de forma segura a esos objetos secundarios, mientras que al mismo tiempo los oculta del código del cliente (que proporcionó la información completa utilizada en la operación de alto nivel). La exposición de tales clases de ayuda en la API pública viola el principio de ocultar información, romper la encapsulación y aumentar la complejidad del código del cliente.

El abuso de DI conduce a objetos sin estado que realmente deberían ser estables porque casi siempre operan con datos específicos de la operación del negocio. Esto no solo es cierto para las clases auxiliares no públicas, sino también para las clases públicas de "servicios empresariales" llamadas desde objetos de interfaz de usuario / presentación. Dichas clases de servicio suelen ser código interno (para una sola aplicación comercial) que no es reutilizable y solo tienen unos pocos clientes (a menudo solo uno) porque dicho código es por naturaleza dominio / caso de uso específico . En tal caso (uno muy común, por cierto) tiene mucho más sentido hacer que la clase de UI instancia directamente la clase de servicio de negocios, pasando datos proporcionados por el usuario a través de un constructor.

Ser capaz de escribir fácilmente pruebas unitarias para código como este es precisamente lo que me llevó a crear el kit de herramientas JMockit . No estaba pensando en el código heredado, sino en la simplicidad y la economía de diseño. Los resultados que logré hasta ahora me convencieron de que la capacidad de prueba realmente es una función de dos variables: la capacidad de mantenimiento del código de producción y las limitaciones de la herramienta de burla utilizada para probar ese código. Entonces, si eliminas todas las limitaciones de la herramienta de burla, ¿qué obtienes?


La capa de abstracción que proporciona Powermock sobre la reflexión parece atractiva, pero hace que las pruebas sean frágiles. Más específicamente:

  1. La reflexión depende de los nombres de las cadenas de los métodos / campos, etc. Cualquier cambio de nombre rompería las pruebas, y luego arreglaría todas las pruebas que accedieran a este método a través de la reflexión. En comparación con una prueba que no requiere reflexión, el IDE refactorizará todas las renovaciones.
  2. Las funciones de Powermock de anotar llamadas a métodos new , estáticos, etc. lo hacen examinar los detalles de implementación de la función. Las pruebas idealmente deben probar la funcionalidad, por ej.

    functionOldImplementation(){ List l = new ArrayList(); } // old implementation changed to new functionNewImplementation(){ List l = new LinkedList(); }

Mocking la new ArrayList() llamada new ArrayList() rompería las pruebas para la refactorización anterior. Las pruebas son más necesarias para ejecutar regresiones y fallan si se hacen de esta manera.

Recientemente encontré este artículo , aborda la mayoría de los puntos planteados en la pregunta, pensé que lo compartiría.

Algunos puntos clave del artículo:

  1. Llevó 1,5 años hacer que PowerMock + Javaassist sea compatible con Java7 desde su introducción. Aquí hay una nota del registro de cambios de PowerMock:

    Change log 1.5 (2012-12-04) --------------------------- Upgraded to Javassist 3.17.1-GA, this means that PowerMock works in Java 7!

  2. El sitio de PowerMock dice:

"Tenga en cuenta que PowerMock está destinado principalmente a personas con conocimiento experto en pruebas unitarias. Ponerlo en manos de desarrolladores junior puede causar más daño que bien".