Otras respuestas han abordado el problema general de cómo escribir una prueba unitaria que comprueba que se produce una excepción. Pero creo que su pregunta realmente está preguntando cómo obtener el código para lanzar la excepción en primer lugar.
Tome su código como ejemplo. Sería muy difícil provocar que su getServerName()
lanzara internamente una excepción en el contexto de una prueba de unidad simple. El problema es que, para que se produzca la excepción, el código (normalmente) debe ejecutarse en una máquina cuya red esté rota. Disputar que eso ocurra en una prueba unitaria es probablemente imposible ... necesitaría configurar erróneamente la máquina antes de ejecutar la prueba.
¿Cuál es la respuesta?
En algunos casos, la respuesta simple es solo tomar la decisión pragmática y no buscar una cobertura de prueba total. Tu método es un buen ejemplo. Debería estar claro desde la inspección del código lo que el método realmente hace. Probarlo no va a probar nada (excepto en el siguiente **
). Todo lo que está haciendo es mejorar sus recuentos de prueba y números de cobertura de prueba, ninguno de los cuales debe ser el proyecto objetivos.
En otros casos, puede ser conveniente separar el código de bajo nivel donde se genera la excepción y convertirlo en una clase separada. Luego, para probar el código de nivel superior que maneja de la excepción, puede reemplazar la clase con una clase simulada que emitirá las excepciones deseadas.
Aquí está su ejemplo dado este "tratamiento". (Esto es un poco artificial ...)
public interface ILocalDetails {
InetAddress getLocalHost() throws UnknownHostException;
...
}
public class LocalDetails implements ILocalDetails {
public InetAddress getLocalHost() throws UnknownHostException {
return InetAddress.getLocalHost();
}
}
public class SomeClass {
private ILocalDetails local = new LocalDetails(); // or something ...
...
public String getServerName() {
try {
InetAddress addr = local.getLocalHost();
return addr.getHostName();
}
catch (Exception e) {
e.printStackTrace();
return "";
}
}
}
ahora a la unidad de prueba de esto, se crea una aplicación "simulacro" de la interfaz ILocalDetails
cuya getLocalHost()
método lanza la excepción que desee en las condiciones apropiadas. A continuación, crea un texto de unidad para SomeClass.getServerName()
, organizando que la instancia de SomeClass
utilice una instancia de su clase "simulada" en lugar de la clase normal. (El último bit podría hacerse utilizando un marco de burla, exponiendo un setter
para el atributo local
o utilizando las API de reflexión.)
Obviamente, tendría que modificar el código para que pueda probarse de esta manera. Y hay límites a lo que puede hacer ... por ejemplo, ahora no puede crear una prueba de unidad para hacer que el método real LocalDetails.getLocalHost()
arroje una excepción. Debe juzgar caso por caso si vale la pena el esfuerzo de hacer esto; es decir, ¿el beneficio de la prueba unitaria supera el trabajo (y la complejidad del código adicional) de hacer que la clase sea comprobable de esta manera? (El hecho de que hay un método static
en la parte inferior de esta es una gran parte del problema.)
**
Hay es un punto hipotético para este tipo de pruebas. En su ejemplo, el hecho de que el código original capte una excepción y devuelva una cadena vacía podría ser ser un error ... dependiendo de cómo se especifique la API del método ... y una prueba de unidad hipotética lo recogería. Sin embargo, en este caso, el error es tan evidente que lo detectarías mientras escribes la prueba de la unidad. Y suponiendo que solucione los errores a medida que los encuentre, la prueba unitaria se vuelve algo redundante. (No es de esperar que alguien reconducir este error en particular ...)
Por curiosidad, ¿por qué es esto una CW? – Uri
Probablemente haya notado que el primer comentario para la mayoría de las preguntas es "debería ser wiki". Éste probablemente tiene más de 6 respuestas válidas, por lo que CW parece razonable. –