¿Cómo pruebo una clase que tiene métodos, campos o clases internas privadas?

Resuelto Raedwald asked hace 16 años • 59 respuestas

¿Cómo uso JUnit para probar una clase que tiene métodos privados internos, campos o clases anidadas?

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

Raedwald avatar Aug 29 '08 23:08 Raedwald
Aceptado

Si tiene una aplicación Java heredada y no puede cambiar la visibilidad de sus métodos, la mejor manera de probar métodos privados es utilizar la reflexión .

Internamente utilizamos ayudantes para obtener/establecer privatevariables private static, así como para invocar privatemétodos private static. Los siguientes patrones le permitirán hacer prácticamente cualquier cosa relacionada con los métodos y campos privados. Por supuesto, no se pueden cambiar private static finallas variables mediante la reflexión.

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

Y para campos:

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

Notas:

  1. TargetClass.getDeclaredMethod(methodName, argClasses)le permite buscar privatemétodos. Lo mismo se aplica para getDeclaredField.
  2. Se setAccessible(true)requiere que juegue con los soldados rasos.
Cem Catikkas avatar Aug 29 '2008 16:08 Cem Catikkas

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

  1. El método privado es código muerto.
  2. Hay un olor a diseño cerca de la clase que estás probando.
  3. El método que estás intentando probar no debe ser privado.
 avatar Aug 29 '2008 16:08

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 huele a código: mi clase es demasiado complicada.

Mi enfoque habitual para abordar estos problemas es crear una nueva clase que contenga las partes interesantes. A menudo, este método y los campos con los que interactúa, y tal vez uno o dos métodos más, 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 nueva y antigua ahora son más simples que la clase original, lo cual es excelente para mí (¡tengo que 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 utilizar las fuerzas de las pruebas unitarias para ayudarle a encontrar buenas clases nuevas.

Jay Bazuzi avatar Sep 09 '2008 14:09 Jay Bazuzi

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

Estrictamente hablando, no debería escribir pruebas unitarias que prueben directamente métodos privados. Lo que deberías estar probando 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 quiere realizar un pequeño cambio interno en la clase, que no afecte el contrato público de la clase, entonces tendrá que modificar su prueba basada en 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 utilizar una herramienta de cobertura de código, como Cobertura , para garantizar que las pruebas unitarias que escriba proporcionen una cobertura decente del código en métodos privados. De esa manera, prueba indirectamente lo que están haciendo los métodos privados y mantiene un mayor nivel de agilidad.

Peter Mortensen avatar Jun 25 '2009 10:06 Peter Mortensen