Saltar al contenido

Mes: junio 2019

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

Caching en Web API Net Core 2.2

Para nadie es sorpresa que la tendencia en el desarrollo con tencologias Backend de Microsoft se orienta cada vez más a NetCore, estando como release candidate (a la fecha de hoy) la versión 3.0.

Hace un tiempo que vengo trabajando con NetCore, inicialmente en proyectos personales y luego en el trabajo. El tema que hoy nos reclama es como aplicar caching y concurrency en las web api cuando se trabaja con Net Core. Para ello, primero recordemos un poco que implica caching.

Cuando nos referimos a caching es válido entender que brindamos un determinado tiempo de vida a una solicitud http, lo cual nos permite no volver a consultar el mismo recurso por el tiempo que se ha determinado, esto nos permite optimizar los tiempos de respuesta y el consumo de recursos en el servidor.

Existen tipos de caching, para entender mejor esta idea, revisemos la siguiente imagen:

caching types

  • Client Cache: Usualmente podemos encontrarlos en el navegador, almacenan las respuestas de las peticiones http individualmente si estas así lo indican, es privado porque los recursos que se están almacenando no se comparten con nadie más.
  • Gateway Cache: Es un cache compartido, los recursos son usados por multiples aplicaciones.
  • Proxy Cache: Tambien es un cache compartido, sin embargo su embergadura es mayor, es usualmente usado por corporaciones grandes o provedores de internet.

Del mismo modo, cuando se trabaja con caching, tenemos que tener un poco más claro que significa el «Modelo de expiración», esta es una forma de indicarle a los clientes, cuanto tiempo va a durar una solicitud, lo cual permite indicarle a las aplicaciones clientes por cuanto tiempo se va a entender que una respuesta http se considera activa. Para conseguir este objetivo se usan dos header comunmente:

  • Expires Hader: Es el más simple, contiene una marca de tiempo de la expiración, pero se asume que las horas entre el cliente y el servidor están sincronizadas.
  • Cache Control Header: Permite indicar el tiempo como «max-age» lo cual indica estará activo por 60 segundos, y public indica quienes pueden realizar el caching de esta respuesta http (client, gateway o proxy).

Es necesario hablar también sobre los modelos de validación o «Validation Model» , estos nos permiten validar si la solicitud http ha sido modificada y de este modo mantenemos la integridad de nuestra solicitud.

  • Strong Validators: Usan los «ETag» para validar si la respuesta ha sido modificada.
  • Weak Validators: No siempre cambian cuando la respuesta lo hace, sólo cambian en cambios considerables, se basan en una etiqueta de «Last-Modified», recordemos que los horarios deben estar sincronizados. También poseen weak Etag.

Finalmente, para culminar con la teoría, es necesario hablar sobre «Cache-control directives», las cuales son las directivas que se pueden enviar en el request y el response http:

  • Response: Tenemos elementos de control que nos indican el tiempo de duración máximo (en segundos) de la solicitud, si es posible almacenarla en el navegador (private) o en el servidor (public) entre otras.
  • Request: Del mismo modo, tenemos elementos que nos valida el tiempo de duración de la respuesta mínimo y máximo entre otras.

Para la demo que vamos a realizar, usaremos un nugget llamado «Marvin.Cache.Headers», luego de instalarlo nos dirigimos al archivo de configuración «Startup» de nuestro web api.

Es necesario agregar en el «ConfigurationService» y en el «Configure» que se debe añadir el uso de cacheheader al pipeline de ejecución, adicionalmente estoy sobreescribiendo el timepo de expiración de la solicitud e indicandole que se debe revalidar.

Sólo con está configuración, ya tenemos habilitado el uso de caching, en su modo más básico. Probemos en postman el uso de lo implementado, primero debemos habilitar el envío de «cache-control» en el header, esto se hace de la siguiente manera:

La petición que llevaremos a cabo, es la siguiente:

Como pueden ver es un GET a un endpoint que en el query esta buscando los libros de un determinado autor. Pongamos un punto de interrupción para validar que la petición a llegado, y veamos la respuesta que recibimos.

Como podemos ver, el tiempo de vida de la petición es 30 segundos, de modo que si se volviera a hacer otra petición, esta no llegaria a nuestro endpoint, en cambio nos indicaria el timepo de vida que aún tiene la solicitud que hemos realizado.

Les dejo link al repositorio en github en el cual pueden encontrar el proyecto completo y el video de youtube donde pueden visualizar las pruebas.

REPO: GITHUB

Saludos.

Deja un comentario