unit test examples example ejemplos create java unit-testing junit annotations

java - test - anotación para hacer público un método privado solo para clases de prueba



junit maven example (12)

Quién tiene una solución para esa necesidad común.

Tengo una clase en mi aplicación.

algunos métodos son públicos, ya que son parte de la API, y algunos son privados, ya que para el uso interno de hacer que el flujo interno sea más legible

ahora, digamos que quiero escribir una prueba unitaria, o más como una prueba de integración, que se ubicará en un paquete diferente, que se le permitirá llamar a este método, PERO, quiero que no se permita la llamada normal a este método si intentas llamar desde las clases de la aplicación en sí

entonces, estaba pensando en algo así

public class MyClass { public void somePublicMethod() { .... } @PublicForTests private void somePrivateMethod() { .... } }

La anotación anterior marcará el método privado como "público para pruebas", lo que significa que la compilación y el tiempo de ejecución se permitirán para cualquier clase que esté bajo el paquete de prueba ... mientras que la compilación y / o el tiempo de ejecución fallarán para cualquier clase que sea no bajo el paquete de prueba.

¿Alguna idea? hay una anotación como esta? ¿Hay una mejor manera de hacer esto?

parece que cuantas más pruebas de unidad escribes, más información tienes para romper tu encapsulación ...



Bueno, aquí tenemos dos cosas que están siendo mezcladas. Lo primero, es cuando necesita marcar algo para usarlo solo en la prueba, lo que estoy de acuerdo con @JB Nizet, usar la anotación de guayaba sería bueno.

Una cosa diferente es probar métodos privados. ¿Por qué deberías probar métodos privados desde afuera? Quiero decir ... Deberías poder probar el objeto por sus métodos públicos y, al final, su comportamiento. Al menos, eso estamos haciendo e intentando enseñar a los desarrolladores junior, que siempre intentan probar métodos privados (como una buena práctica).


Considere el uso de interfaces para exponer los métodos API, utilizando fábricas o DI para publicar los objetos de manera que los consumidores los conozcan solo mediante la interfaz. La interfaz describe la API publicada. De esta forma, puede hacer que lo que desee público en los objetos de implementación y los consumidores de ellos vean solo los métodos expuestos a través de la interfaz.


La forma común es proteger el método privado o privado del paquete y poner la prueba unitaria para este método en el mismo paquete que la clase bajo prueba. Guava tiene una anotación @VisibleForTesting , pero es solo para fines de documentación.



No puedes hacer esto, ¿cómo podrías incluso compilar tus pruebas? El compilador no tomará la anotación en cuenta.

Hay dos enfoques generales para esto

El primero es usar la reflexión para acceder a los métodos de todos modos

El segundo es usar package-private en lugar de private, luego tener tus pruebas en el mismo paquete (pero en un módulo diferente). En esencia, serán privados para otro código, pero sus pruebas aún podrán acceder a ellos.

Por supuesto, si haces pruebas de caja negra, no deberías acceder a los miembros privados de todos modos.


O puede extraer este método a algún objeto de estrategia . En este caso, puede probar fácilmente la clase extraída y no hacer que el método sea público o algo mágico con reflection / bytecode.


Por mucho que sé, no hay anotaciones como esta. La mejor manera es usar la reflexión como sugirieron algunos de los otros. Mira esta publicación:
¿Cómo pruebo una clase que tiene métodos privados, campos o clases internas?

Solo debe tener cuidado al probar el resultado de la excepción del método. Por ejemplo: si espera una IllegalArgumentException, pero en cambio obtendrá "null" (Clase: java.lang.reflect.InvocationTargetException).
Un colegue mío me propuso usar el marco powermock para estas situaciones, pero aún no lo he probado, así que no tengo idea de qué es exactamente lo que puede hacer. Aunque he utilizado el framework Mockito en el que se basa y eso también es un buen marco (pero creo que no resuelve el problema de la excepción del método privado).

Aunque es una gran idea tener la anotación @PublicForTests.

¡Aclamaciones!


Recientemente lanzamos una biblioteca que ayuda mucho a acceder a campos privados, métodos y clases internas a través de la reflexión: BoundBox

Para una clase como

public class Outer { private static class Inner { private int foo() {return 2;} } }

Proporciona una sintaxis como:

Outer outer = new Outer(); Object inner = BoundBoxOfOuter.boundBox_new_Inner(); new BoundBoxOfOuter.BoundBoxOfInner(inner).foo();

Lo único que tienes que hacer para crear la clase BoundBox es escribir @BoundBox(boundClass=Outer.class) y la clase BoundBoxOfOuter se generará instantáneamente.


Si la cobertura de su prueba es buena en todos los métodos públicos dentro de la clase probada, los métodos privados llamados por el público se probarán automáticamente, ya que hará valer todo el posible caso.

El JUnit Doc dice:

Probar métodos privados puede ser una indicación de que esos métodos deberían moverse a otra clase para promover la reutilización. Pero si debe ... Si está utilizando JDK 1.3 o superior, puede usar el reflejo para subvertir el mecanismo de control de acceso con la ayuda del PrivilegedAccessor. Para detalles sobre cómo usarlo, lee este artículo.


Un artículo sobre Prueba de métodos privados establece algunos enfoques para probar el código privado. el uso de la reflexión impone una carga adicional al programador para recordar que, si se realiza la refactorización, las cadenas no cambian automáticamente, pero creo que es el enfoque más limpio.


dp4j tiene lo que necesitas. Esencialmente, todo lo que tiene que hacer es agregar dp4j a su classpath y siempre que un método anotado con @Test (anotación de JUnit) llame a un método que sea privado funcionará (dp4j inyectará la reflexión requerida en tiempo de compilación). También puede usar la anotación @TestPrivates de dp4j para ser más explícito.

Si insiste en anotar también sus métodos privados, puede usar la anotación @VisibleForTesting de Google.