leer - java read xml string
¿Cómo probar un constructor privado en la aplicación Java? (7)
@Test
public//
void privateConstructorTest() throws Exception {
final Constructor<?>[] constructors = Utils.class.getDeclaredConstructors();
// check that all constructors are ''private'':
for (final Constructor<?> constructor : constructors) {
Assert.assertTrue(Modifier.isPrivate(constructor.getModifiers()));
}
// call the private constructor:
constructors[0].setAccessible(true);
constructors[0].newInstance((Object[]) null);
}
Esta pregunta ya tiene una respuesta aquí:
Si una clase contiene un montón de métodos estáticos, para asegurarse de que nadie por error inicializa una instancia de esta clase, hice un constructor privado:
private Utils() {
}
Ahora ... ¿cómo podría ser probado esto, dado que el constructor no puede ser visto? ¿Puede ser esta prueba cubierta en absoluto?
para asegurarse de que nadie por error inicializa una instancia de esta clase
Por lo general, lo que hago es cambiar el método / constructor de la visibilidad del paquete privado al predeterminado. Y utilizo el mismo paquete para mi clase de prueba, por lo que a partir de la prueba se puede acceder al método / constructor, incluso si no es desde el exterior.
Para hacer cumplir la política de no instanciar la clase, puede:
- lanza UnsupportedOperationException ("no crear instancias de esta clase!") del constructor vacío predeterminado.
- declare el resumen de clase: si solo contiene métodos estáticos, puede llamar a los métodos estáticos pero no crear una instancia, a menos que lo subclases.
o aplique ambos 1 + 2, aún puede crear una subclase y ejecutar el constructor si su prueba comparte el mismo paquete que la clase objetivo. Esto debería ser bastante "a prueba de errores"; los codificadores maliciosos siempre encontrarán una solución :)
Si tiene un constructor privado, se llama desde algún método no tan privado de su código. Entonces prueba ese método y su constructor está cubierto. No hay virtud religiosa en tener una prueba por método. Está buscando una función o, mejor aún, un nivel de cobertura de sucursal, y puede conseguirlo simplemente ejercitando el constructor a través de la ruta del código que lo utiliza.
Si la ruta del código es intrincada y difícil de probar, quizás necesite refactorizarla.
Usando la reflexión, puede invocar un constructor privado:
Constructor<Util> c = Utils.class.getDeclaredConstructor();
c.setAccessible(true);
Utils u = c.newInstance(); // Hello sailor
Sin embargo, puedes hacer que incluso eso no sea posible:
private Utils() {
throw new UnsupportedOperationException();
}
Al lanzar una excepción en el constructor, evita todos los intentos.
Yo también haría que la clase sea final
, solo "porque":
public final class Utils {
private Utils() {
throw new UnsupportedOperationException();
}
}
Pruebe la intención del código ... siempre :)
Por ejemplo: si el punto de que el constructor es privado no se ve, entonces lo que necesita probar es este y nada más.
Utilice la API de reflexión para consultar los constructores y validar que tienen el conjunto de atributos privados.
Haría algo como esto:
@Test()
public void testPrivateConstructors() {
final Constructor<?>[] constructors = Utils.class.getDeclaredConstructors();
for (Constructor<?> constructor : constructors) {
assertTrue(Modifier.isPrivate(constructor.getModifiers()));
}
}
Si desea tener una prueba adecuada para la construcción del objeto, debe probar la API pública que le permite obtener el objeto construido. Esa es la razón por la que debería existir dicha API: para construir los objetos correctamente, así que debes probarlo :).
No lo hagas El constructor es privado. Eso es todo lo que necesitas. Java hace cumplir su privacidad.
No pruebes la plataforma.
Si agrega una excepción en el constructor como, por ejemplo:
private Utils() {
throw new UnsupportedOperationException();
}
La invocación de constructor.newInstance()
en la clase de prueba arrojará una InvocationTargetException
lugar de su UnsupportedOperationException
, pero la excepción deseada estará contenida en la arrojada.
Si desea afirmar el lanzamiento de su excepción, puede arrojar el objetivo de la excepción de invocación, una vez que la excepción de invocación ha sido capturada.
Por ejemplo, usando jUnit 4 puedes hacer esto:
@Test(expected = UnsupportedOperationException.class)
public void utilityClassTest() throws NoSuchMethodException, IllegalAccessException, InstantiationException {
final Constructor<Utils> constructor = Utils.class.getDeclaredConstructor();
constructor.setAccessible(true);
try {
constructor.newInstance();
} catch (InvocationTargetException e) {
throw (UnsupportedOperationException) e.getTargetException();
}
}