¡Buen día! El artículo tratará sobre un punto completamente insignificante en la codificación.
Por ejemplo, muchos de mis colegas dijeron: ¡ Doch, das ist ganz normal! "¡Y qué, todas las reglas, encontré algo de qué quejarme!" Pero no obstante.
Hay algunas cosas sobre la codificación que me cabrean. Bueno, en realidad no pocos. :), cuanto mayor me hago, más y más cosas así, el personaje no mejora. Pero en la parte superior, cuando los desarrolladores escriben pruebas para métodos privados. ¡Oh no! Cuando para esto eliminan la palabra privado del método y el método se convierte en paquete privado.
Entonces, revisa una clase como esta, líneas en 3K, escritas en las mejores tradiciones de programación procedimental, y hay 10 métodos públicos, 10 privados y 15 más de paquetes privados. Y no hemos oído hablar de las interfaces: este es un servicio, ¡inyectémoslo así! Ok, piensa, ahora nos arremangaremos, trasladaremos todos los métodos públicos a la interfaz, helper-s, a un paquete separado; en resumen, cortaremos esta locura en pedazos según SRP. Pero luego descubres que los métodos de paquetes privados se han estado moviendo desde otros lugares durante mucho tiempo. ¡Así que hemos descartado todas las clases en un paquete! Si se puede hacer un mal uso de algo, seguro que se utilizará mal, como dicen.
Sí, todo el mundo lo sabe, no es necesario que escriba pruebas para métodos privados, si hace esto, entonces algo está mal con el diseño, y así sucesivamente. Pero, maldita sea, la gente lo hace de todos modos, y debo decir que no sin razón. Imagine que la clase anterior no tiene cobertura de prueba en absoluto. Y necesitas refactorizar. Así es como entran en juego los métodos privados de paquetes. Pero, ¿cómo podemos ser? Cortaron Whitebox de Mockito, por supuesto que permaneció en PowerMock , pero por el bien de esto, arrastrando PowerMock al proyecto, y la sintaxis no es mejor que una llamada directa a través de la reflexión. Por supuesto, puedes escribir tu propia bicicleta, pero ... Y no funciona así.
Pero imagina que tenemos una interfaz para acceder a elementos privados de una clase: métodos, campos. Qué diablos, dices, el tipo está trabajando duro. Pero así:
Hay una clase:
public class ObjectWithPrivates {
private final AtomicInteger count = new AtomicInteger(0);
private String name;
private String methodToTest(String in) {
return name + in + count.incrementAndGet();
}
}
Prueba:
interface TestPrivates {
void setName(String name);
String methodToTest(String in);
AtomicInteger getCount();
}
@Test
void testPrivates() {
ObjectWithPrivates obj = new ObjectWithPrivates();
TestPrivates objWithPrivates = API.lookupPrivatesIn(obj)
.usingInterface(TestPrivates.class);
objWithPrivates.setName("Andromeda");
String in = objWithPrivates.methodToTest("in");
AtomicInteger count = objWithPrivates.getCount();
Assertions.assertEquals("Andromedain1", in);
Assertions.assertEquals(1, count.get());
}
Como puede ver, usando la interfaz, podemos buscar métodos privados y acceder a campos privados. Bueno, puedes saber de inmediato lo que está sucediendo en el código. Tenga en cuenta que todas las manipulaciones ocurren con obj y puede, por ejemplo, establecer todos los campos privados de obj y luego extraer el método público.
Puede acceder a los campos / métodos privados de la clase principal:
TestPrivates accessToPrivates = API.lookupPrivatesIn(obj) .lookupInSuperclass() .usingInterface(TestPrivates.class);
O puede extraer métodos estáticos:
TestPrivates accessToPrivates = lookupPrivatesIn(SomePOJOClass.class) .usingInterface(TestPrivates.class); accessToPrivate.someStaticPrivateMethod();
O puede crear un objeto usando un constructor privado.
Debajo del capó, hay reflexión estándar y Proxy dinámico, sin dependencias adicionales.
Aquí hay un enlace al proyecto testprivates . Úselo solo para pruebas.
Todo con la venida, ¡no te enfermes!