Te estás acercando a esto de la manera incorrecta. Simplemente pruebe su funcionalidad: si se produce una excepción, la prueba fallará automáticamente. Si no se produce ninguna excepción, todas sus pruebas se volverán verdes.
He notado que esta pregunta genera interés de vez en cuando, así que me expandiré un poco.
Antecedentes de las pruebas unitarias
Cuando realiza pruebas unitarias, es importante que se defina lo que considera una unidad de trabajo. Básicamente: una extracción de su base de código que puede o no incluir múltiples métodos o clases que representan una sola pieza de funcionalidad.
O, como se define en The art of Unit Testing, 2nd Edition de Roy Osherove , página 11:
Una prueba de unidad es una pieza de código automatizada que invoca la unidad de trabajo que se está probando y luego verifica algunos supuestos sobre un resultado final único de esa unidad. Una prueba unitaria casi siempre se escribe utilizando un marco de prueba unitaria. Se puede escribir fácilmente y se ejecuta rápidamente. Es confiable, legible y mantenible. Es consistente en sus resultados siempre que el código de producción no haya cambiado.
Lo importante es darse cuenta de que una unidad de trabajo generalmente no es solo un método, sino que en el nivel más básico es un método y luego se encapsula en otra unidad de trabajo.
Idealmente, debe tener un método de prueba para cada unidad de trabajo por separado para que siempre pueda ver de inmediato dónde van las cosas mal. En este ejemplo, hay un método básico llamado getUserById()
que devolverá un usuario y hay un total de 3 unidades de trabajo.
La primera unidad de trabajo debe probar si se devuelve o no un usuario válido en el caso de una entrada válida o no válida.
Aquí se deben manejar las excepciones lanzadas por el origen de datos: si no hay ningún usuario presente, debe haber una prueba que demuestre que se produce una excepción cuando no se puede encontrar al usuario. Una muestra de esto podría ser la IllegalArgumentException
que se captura con la @Test(expected = IllegalArgumentException.class)
anotación.
Una vez que haya manejado todos sus casos de uso para esta unidad básica de trabajo, sube de nivel. Aquí haces exactamente lo mismo, pero solo manejas las excepciones que provienen del nivel justo debajo del actual. Esto mantiene su código de prueba bien estructurado y le permite ejecutar rápidamente la arquitectura para encontrar dónde van las cosas mal, en lugar de tener que saltar por todas partes.
Manejo de una entrada válida y defectuosa de las pruebas
En este punto, debería quedar claro cómo manejaremos estas excepciones. Hay 2 tipos de entrada: entrada válida y entrada defectuosa (la entrada es válida en sentido estricto, pero no es correcta).
Cuando trabaja con una entrada válida , está estableciendo la expectativa implícita de que cualquier prueba que escriba funcionará.
Tal llamada al método puede tener este aspecto: existingUserById_ShouldReturn_UserObject
. Si este método falla (por ejemplo, se produce una excepción), entonces sabe que algo salió mal y puede comenzar a cavar.
Al agregar otra prueba ( nonExistingUserById_ShouldThrow_IllegalArgumentException
) que usa la entrada defectuosa y espera una excepción, puede ver si su método hace lo que se supone que debe hacer con una entrada incorrecta.
TL; DR
Intentaba hacer dos cosas en su prueba: verificar la entrada válida y defectuosa. Al dividir esto en dos métodos para que cada uno haga una cosa, tendrá pruebas mucho más claras y una visión general mucho mejor de dónde van las cosas mal.
Al tener en cuenta la unidad de trabajo en capas, también puede reducir la cantidad de pruebas que necesita para una capa que es más alta en la jerarquía porque no tiene que tener en cuenta todo lo que podría haber salido mal en las capas inferiores: las capas debajo de la actual son una garantía virtual de que sus dependencias funcionan y si algo sale mal, está en su capa actual (suponiendo que las capas inferiores no arrojen ningún error).