Saltar al contenido

Etiqueta: lima

Grabar log de errores en db y archivo con Spring Boot

Llevo ya algunas semanas revisando cursos sobre Spring, como he mencionado en publicaciones anteriores, el trabajo me lleva a desarrollar más en tecnologías de Microsoft. Sin embargo, conforme voy aprendido más de spring, me interesa más por lo pontente que es y el beneficio que brinda al evitar la repetición de código que no le suma nada a la lógica de negocio o ”  boilerplate code “.

El post de hoy, lo centrare en el grabado de logging cuando tenemos una aplicación hecha con spring boot, como saben el log es fundamental dado que un buen log nos permite resolver los problemas de nuestro aplicativo sin mucha demora, en un post posterior explicare lineamientos para generar un buen log y buenas practicas en el mismo. Sin embargo me interesa hacer un post de esto acá porque he tenido que revisar mucho la documentación para poder configurar el log como lo necesitaba en spring y no pude encontrar ningún lugar donde expliquen detenidamente como poder realizar esto.

El log que grabaremos se realizará en base de datos (postgres) y un archivo de texto (.txt), se pueden tener multiples tipos (niveles) de log, que nos permiten medir la usabilidad de los features, los errores y las caidas fatales del sistema, para la demo me enfocare en los errores y explicare como en spring podemos capturar todos los errores que se generen, grabarlos en base de datos y el archivo de texto y al usuario mostrarle un mensaje de texto genérico y un código vinculado a nuestro registro de error.

APLICATIVO

Estoy usando Intellij IDEA como IDE para el desarrollo de esta demo, y la aplicación se divide en repository, service y controller. Considerando que el repository y service tenemos una implementación para las interfaces que definimos. Además, en repository tenemos una capa para hacer el mapping a entidades de lo recibido por la base de datos.

Project files de Spring boot

Para grabar los logs, usar log4j2 que es una librería de amplia trayectoria y bien documentada, para configurarla en la sección de resources de nuestra aplicación es necesario crear un archivo de configuración, este puede ser un xml, json o un properties. En mi caso cree un “log4j2.properties” .

Archivo de configuración del log

En el properties de spring es necesario indicarle que tenemos un archivo de configuración de log con las siguientes sentencias:

Configuración en el application.properties para el log

En el log4j2.properties que hemos creado es necesario indicar la siguiente configuración.

Configuración del log en log4j2.properties

En esta estamos indicando el indicando al configuración de la base de datos, es necesario indicar cada columna de la tabla que hemos destinado para los logs en base de datos con los valores que se van a considerar para cada columna. También está la configuración para el archvo de texto, finalmente se indica que ambos appender deben ser utilizados y el nivel mínimo del log.

También es posible indicar en el log variables configuradas por nosotros, para mi caso es necesario saber el endpoint que se está consumiendo, el nombre del método del endpoint, el nombre del método donde el error ocurrio, un guid para vincular el error a un identificador único entre otros valores. Esto podemos conseguirlo seteando variables como propiedades del sistema y luego leyendo en nuestro log4j2.propierties.

Seteo de variables como propiedades del sistema
Obtenemos la propiedad del sistema en log4j2.properties

Una explicación didáctica de esta configuración así como algunas cosas que no pongo en el post para no hacerlo muy extenso lo encuentran en el video. Quedan muchos puntos por detallar más que desarrolloraré en otros posts, espero que les haya sido de utilidad y como siempre dejo los links al repositorio para que revisen ustedes el código.

REPO: GITHUB

Saludos.

1 comentario

Llamar un Mock Object dos veces con distintos resultados

Recientemente en el trabajo nos enfrentamos a un escenario cuando estabamos creando los test unitarios de un proyecto. Usando Moq como librería para el mocking queriamos que al llamar a un mismo método en el repositorio obtengamos distintos resultados por cada llamada. Ya en un post anterior he tratado un tema similiar a este con test unitarios, pero en los escenarios más simples es sólo necesario realizar un llamado obtener el resultado desarrollar cierta lógica de negocio con este resultado y evaluar los aserciones en el test.

Me parecio interesante desarrollar un poco más este tema y por eso hago este post, en el les explicaré un poco sobre las distintas opciones que tenemos para poder obtener distintos resultados al llamar a mock object con Moq, siendo una de estas opciones “SetupSequence” que es un overload al método setup que existe en esta librería, lo que podría generar un problema es que este overload es relativamente reciente, dado que recién se a incorporado como parte de la librería el 20 de junio del 2019. Y la otra opción es el uso de una estructura de datos como las queue o colas.

Para el desarrollo del post, me valdré del mismo proyecto que trabajamos en el post pasado, simplemente he añadido nuevos método en la capa de aplicación y en el repositorio y nuevos test unitarios.

APLICACION

Nuevo método en la capa de aplicación

Este método, como ven simplemente llama dos veces al mismo método del repositorio, con distintos parametros de entrada y retorna la concatenación de ambos resultados.

REPOSITORIO

Nuevo método en la capa de repositorio

Como ven, en el repositorio también se ha creado un nuevo método acá se está intentando simular que se llega a una base de datos, pero por fines prácticos se está devolviendo el nombre completo para todas las llamadas. Veamos los nuevos test unitarios desarrollados.

TEST

Uso de SetupSequence

Como pueden ver, con el uso de “SetupSequence” es posible realizar más de “Returns” los cuales, se van devolviendo conforme se van llamando, de manera tal que en el primer llamado desde la capa de aplicación, se devuelve “walberth”, y en el segundo “angela” y finalmente, se retorna la concatenación.

Uso de queue (Colas)

La otra forma de conseguir el mismo resultado, es valiendonos del uso de colas, como saben esta estructura de datos es del tipo FIFO (first in, first out), de modo que cada ves que llamemos a nuetro moq, y su objeto de retorno es del tipo Queue va a devolver los objetos de este modo.

Espero que les sirva de ayuda como hemos podido resolver este escenario, tal ves con un caso tan común, pero cuando ocurre puede que nos tome un par de horas ver la forma de darle solución. Como siempre, dejo el video del desarrollo de esta solución y los links a github.

REPO: GITHUB

Saludos.

1 comentario

Unit Test y Mocking en NetCore

Cuando empezamos a desarrollar, sea el lenguaje que nos adopte incialmente no solemos tener en consideración los test unitarios y mucho menos el mocking. Si nos dedicamos a este mundo del desarrollo, tarde o temprano vamos a tener que llegar a saber para que sirven y como implementarlos, y de esto de lo que busco escribir un poco hoy.

TEST UNITARIOS

Los test unitarios son secciones de código de escribimos, cuyo objetivo es probar el funcionamiento y funcionalidad de otros métodos que hayamos desarrollado. Es importante tener claro el concepto de atomicidad al querer realizar un test unitarios, dado que el método a probar que se ha desarrollado debemos intentar que posea una única responsabilidad, de manera tal que nuestros test unitarios puedan ser atómico.

MOCKING

Cuando nos referimos a mocking, debemos tener claro que se tiene que llevar a cabo con una prueba unitaria, y lo que nos permite es abstraer el método que queremos probar de otras dependencías que no se están probando. De tal manera, podemos aislar nuestro test unitario y conseguir que sean realmente atómicos.

En el ejemplo que llevaremos a cabo, explicare como implementar un test unitario en Net Core 2.2, usando una librería para poder aplicar mocking en nuestro test. Para conseguir esto, usaremos XUnit para el test unitaio y Moq para el mocking. Es importante recalcar que existen otras opciones y que los conceptos que se aplicarán en la demo, puedes tranquilamente extrapolarse a alguna otra librería que se quiera usar.

Para empezara crear nuestro proyecto, se tiene la siguiente estructura en un proyecto demo:

Distribución del proyecto demo
Nuget utilizados en el test unitario

La arquitectura no es lo importante en esta demo, pero basicamente tenemos una capa de presentación (aplicación consola), una capa de aplicación y una de repositorio, en esta última se debe tener acceso a la base de datos. Las pruebas se dividirán de la siguiente manera:

  1. Para explicar los test unitarios se tiene un método en la capa de aplicación un método que recibe el nombre y apellido de una persona y lo regresa concatenado, teniendo varientes si se ha ingreso el nombre o el apellido en vacio.
  2. Probaremos el mocking simulando que estamos accediendo al repositorio y desde este a una base de datos en donde obtenemos un listado de nombres de personas.
Capa de aplicación
Capa de repositorio

En el proyecto de test unitarios, se crearon los siguientes test unitarios:

  • El primero prueba el escenario ideal del método que desarrollamos, notemos que en la primera parte de nuestro test, estamos preparando la información, liego consumimos el método desarrollado y finalmente evaluamos el resultado con los assert que nos brinda xunit.
  • En el segundo test unitario, probamos el escenario en el que a nuestro método no se le proporcione la información necesaria. Se sigue el mismo formato con la organización de los pasos para las pruebas (preparar la información, llamar al método y finalmente evaluar los resultados).
  • Para realizar la prueba del mocking, es importante realizar la inyección de dependencia del repositorio en nuestra aplicación, dado que lo que buscamos con el mocking es poder simular el acceso en este repositorio, Luego, en el test creamos el mock con la interfaz de nuestro repositorio, le indicamos en “Setup” con una expresión lambda el método que vamos a probar, y en este punto podríamos proporcionale la información que sea necesaria para consumir este método de ser esto necesario y finalmente le indicamos lo que va a retornar, para conseguir esto hemos debido crear un objeto del mismo tipo que retorna nuestro método y indicarlo dentro de “Returns”. Finalmente, le pasamos nuestro mock al construtor de nuestra aplicación y llamamos al método a probar.
Inyección de dependencia
Mocking usando moq en NetCore

Finalmente, corremos nuestros test unitarios y tenemos el siguiente resultado:

Como podemos ver, lo importante del test unitario es poder realizar pruebas atómicas del código que escribimos y con esta finalidad quitarle la responsabilidad como obtener objetos que escapan a lo que buscamos probar (como conexiones a base de datos o otros métodos). Y con esta finalidad nos apoyamos del mocking, existen muchas cosas más que se pueden llevar a cabo con Xunit, e incluso más con Moq, ambas librerías usadas para esta demo, Más adelante realizaré más post en los cuales detallo un poco las características de ambas, espero que encuentren útil el post, les dejo el video y el link de github del proyecto realizado.

REPO: GITHUB

Saludos.

Deja un comentario