Configurando los Mocks con Moq

Los Mocks son una parte fundamental para poder realizar test unitarios aislando completamente los módulos. Como ya hemos visto muchas veces, los Mocks nos permiten imitar los objetos de los que depende nuestro módulo a testear de forma controlada. Son bastante sencillos de crear, pero no tanto de configurar. Además, al usar técnicas como TDD, tenemos que adelantarnos a nuestro desarrollo y pensar en muchos casos que llamadas vamos a hacer (o deberíamos hacer) al resto de módulos.

El comportamiento de los mocks con MOQ se puede configurar de tal manera que podamos indicar qué respuestas van a dar los métodos que se invoquen, si queremos que devuelvan excepciones o incluso que disparen eventos. MOQ también nos permite verificar si se han invocado a los métodos que esperábamos con los parámetros adecuados. Veamos cómo:

Configurando con el método setup

MOQ ofrece un método para los objetos de tipo mock creados llamado Setup que nos permite configurar cómo van a responder lo métodos del mock que invoquemos. Por ejemplo, si tenemos una interfaz como la siguiente:

mock

Podemos configurar, por ejemplo, la llamada a IsProductAvalaible diciéndole que cuando se la invoque con un id de producto igual a 2 devuelva true:

mock2

Además de pasar con valor concreto, MOQ nos permite configurar los parámetros de entrada con distintas fórmulas:

  • Cualquier valor: It.IsAny
  • Parámetros que encajen con una función: It.Is
  • Parámetros en un rango: It.IsInRange
  • Parámetros que encajen con una expresión regular: It.IsRegex
  • Parámetros distintos de null: It.IsNotNull
  • Parámetros en una secuencia especificada: It.IsIn o It.IsNotIn

Por ejemplo, para hacer que nuestro método anterior devuelva siempre true cuando se le pase un entero impar se podría hacer con la siguiente línea:

mock3

En el ejemplo anterior, estamos probando un método de nuestro servicio que nos devuelve el total de productos disponibles. Simplificando el ejemplo con un objeto sencillo producto cuyo id se le pasa por constructor y creando 4 productos con 3 ids impares, podemos esperar que el total de productos disponibles deberá ser 3.

Verificando

En las últimas versiones de MOQ han unificado los métodos de setup y expect. Ahora para probar que se han invocado a las funciones correctas y el número correcto de veces, usaremos solamente el método Setup para configurar el mock y comprobaremos con el método Verify del mock.

Supongamos que queremos crear un método que compruebe que productos están disponibles y pida un reabastecimiento de los productos que no lo están. Siguiendo con el ejemplo anterior tendría algo así:

mock4

El método StockUpNonAvailableProduct no devuelve ningún valor, por lo que la forma más apropiada de probarlo es verificando que se invoca llamando a Verify con la llamada al método. Adicionalmente Moq nos permite comprobar con VerifyAll que se han invocado a todos los métodos marcados como Verifiable del mock.

Excepciones

Otra de nuestras necesidades al realizar tests unitarios es probar cómo se comporta nuestro módulo frente a las excepciones esperadas del resto de módulos. Para configurar un mock y hacer que lance una excepción, basta por sustituir el método Returns del Setup por Throws. Por ejemplo, supongamos que llamando al método IsProductAvailable este nos puede devolver una excepción de tipo ArgumentException y que nuestro método OrderProduct devuelve una excepción de tipo NotAvalaibleException en este caso:

mock5

Con el ejemplo anterior, IsProductAvailable lanzará la excepción de tipo ArgumentException pero el test espera a que el resultado sea una excepción de tipo NotAvalaibleException mediante [ExpectedException(typeof(NotAvalaibleException))]. De hecho, no es necesario el Assert.Fail del final en este caso concreto.

Y mucho más

MOQ ofrece muchas opciones más como poder disparar evento, configurar propiedades guardando su estado (Stubs),  configurar miembros protected y otras funciones avanzadas que no suelen ser tan frecuentes creando nuestros tests unitarios, incluso pueden ser síntoma de que nos estamos complicando demasiado con nuestros tests.

JavierSanzNietoJavier Sanz

 .NET Architect | Soluciones Microsoft | SOGETI ESPAÑA

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s