Pregunta ¿Cómo pruebo una función privada o una clase que tiene métodos privados, campos o clases internas?


¿Cómo pruebo la unidad (usando xUnit) una clase que tiene métodos privados internos, campos o clases anidadas? O una función que se hace privada al tener enlace interno (static en C / C ++) o está en privado (anónimo) espacio de nombres?

Parece malo cambiar el modificador de acceso para un método o función solo para poder ejecutar una prueba.


2265


origen


Respuestas:


Si tienes algo de un legado Java aplicación, y no tiene permitido cambiar la visibilidad de sus métodos, la mejor manera de probar métodos privados es usar reflexión.

Internamente estamos usando ayudantes para obtener / configurar private y private static variables, así como invocar private y private static métodos. Los siguientes patrones le permitirán hacer casi cualquier cosa relacionada con los métodos y campos privados. Por supuesto que no puedes cambiar private static final variables a través de la reflexión

Method method = targetClass.getDeclaredMethod(methodName, argClasses);
method.setAccessible(true);
return method.invoke(targetObject, argObjects);

Y para los campos:

Field field = targetClass.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object, value);

Notas:
  1. targetClass.getDeclaredMethod(methodName, argClasses) te deja ver private métodos. Lo mismo aplica para    getDeclaredField.
  2. El setAccessible(true) es necesario para jugar con soldados.


1416



La mejor manera de probar un método privado es a través de otro método público. Si esto no se puede hacer, entonces una de las siguientes condiciones es verdadera:

  1. El método privado es código muerto
  2. Hay un olor de diseño cerca de la clase que está probando
  3. El método que intentas probar no debe ser privado

506



Cuando tengo métodos privados en una clase que son lo suficientemente complicados como para sentir la necesidad de probar los métodos privados directamente, eso es un olor a código: mi clase es demasiado complicada.

Mi enfoque habitual para abordar estos problemas es extraer una nueva clase que contenga los bits interesantes. A menudo, este método y los campos con los que interactúa, y tal vez otro método o dos se pueden extraer en una nueva clase.

La nueva clase expone estos métodos como 'públicos', por lo que son accesibles para pruebas unitarias. Las clases nuevas y antiguas ahora son más simples que la clase original, lo cual es genial para mí (¡necesito mantener las cosas simples, o me pierdo!).

Tenga en cuenta que no estoy sugiriendo que las personas creen clases sin usar su cerebro. El punto aquí es usar las fuerzas de las pruebas unitarias para ayudarlo a encontrar buenas clases nuevas.


271



He usado reflexión hacer esto para Java en el pasado, y en mi opinión fue un gran error.

Estrictamente hablando, deberías no estar escribiendo pruebas unitarias que prueben directamente los métodos privados. Lo que tu debería be testing es el contrato público que la clase tiene con otros objetos; nunca debes probar directamente las partes internas de un objeto. Si otro desarrollador desea hacer un pequeño cambio interno a la clase, lo que no afecta el contrato público de las clases, entonces él / ella tiene que modificar su prueba basada en la reflexión para asegurarse de que funcione. Si hace esto repetidamente a lo largo de un proyecto, las pruebas unitarias dejan de ser una medida útil del estado del código y comienzan a convertirse en un obstáculo para el desarrollo y una molestia para el equipo de desarrollo.

Lo que recomiendo hacer en su lugar es usar una herramienta de cobertura de código como Cobertura, para garantizar que las pruebas de la unidad que escribe brinden una cobertura decente del código en métodos privados. De esta manera, prueba indirectamente lo que hacen los métodos privados y mantiene un nivel más alto de agilidad.


229



De este artículo: Prueba de métodos privados con JUnit y SuiteRunner (Bill Venners), básicamente tienes 4 opciones:

  • No pruebes los métodos privados.
  • Proporcione acceso al paquete de métodos.
  • Use una clase de prueba anidada.
  • Usa la reflexión

187



En general, una prueba unitaria está destinada a ejercer la interfaz pública de una clase o unidad. Por lo tanto, los métodos privados son detalles de implementación que no se espera que prueben explícitamente.


96



Solo dos ejemplos de dónde me gustaría probar un método privado:

  1. Rutinas de descifrado - Yo no lo haría quiero hacerlos visibles para que cualquiera vea solo por por el bien de las pruebas, de lo contrario cualquiera puede úsalos para descifrar. Pero son intrínseco al código, complicado, y la necesidad de trabajar siempre (la excepción obvia es la reflexión que se puede usar para ver incluso los métodos privados en la mayoría de los casos, cuando SecurityManager no está configurado para evitar esto).
  2. Creando un SDK para la comunidad consumo. Aquí el público toma una totalmente diferente significado, ya que este es un código que todo el mundo puede ver (no solo interno a mi aplicación). pongo codificar en métodos privados si no lo hago quiero que los usuarios de SDK lo vean - I no veo esto como un olor a código, simplemente cómo funciona la programación de SDK. Pero de Por supuesto, todavía tengo que probar mi métodos privados, y están donde la funcionalidad de mi SDK en realidad vive.

Entiendo la idea de solo probar el "contrato". Pero no veo que uno pueda abogar en realidad por no probar el código: su millaje puede variar.

Entonces mi compensación implica complicar los JUnits con reflexión, en lugar de comprometer mi seguridad y SDK.


56



Los métodos privados son llamados por un método público, por lo que las entradas a sus métodos públicos también deben probar los métodos privados que son llamados por esos métodos públicos. Cuando falla un método público, puede ser una falla en el método privado.


53