[Moles] Pruebas unitarias de métodos no deterministas
Continuamos con la serie de post relacionados con Moles. Ya vimos una introducción y stubs.
Es este caso concreto vamos a ver como podemos hacer pruebas unitarias sobre métodos no deterministas.
¿Qué son los métodos o funciones no deterministas?
Pues son aquellos que devuelven un resultado diferente con un conjunto específico de valores de entrada cada vez que les llamamos o támbien por que dependen de variables del entorno (Como vamos a ver en nuestro caso del ejemplo).
Imaginaros que tenemos que llamar a una API que fue desarrollada por un tercero y que tiene un método como el siguiente:
public class Discounts
{
/// <summary>
/// Gets the discount.
/// </summary>
/// <returns></returns>
public int GetDiscount()
{
var dayOfWeek = DateTime.Now.DayOfWeek;
return dayOfWeek == DayOfWeek.Saturday ? 20 : 5;
}
}
¿Veis el problema?
Se trata de un problema de diseño, es decir, podrían haber dado la opción de pasar la fecha como parámetro, peroooo!!! no ha sido así y ahora tenemos un problema, porque dependiendo del día que se ejecute la prueba unitaria nos dará un resultado u otro.
Entonces ¿Esperamos a sea sábado para probar el descuento del 20% y cualquier día de la seman que no sea sábado para probar que devuleve el 5%?
Pues la respuesta es no, ya que gracias los Moles vamos a poder testear este código cualquier día de la semana.
Para poder realizar las pruebas unitarias tenemos que generar los Moles de la librería mscorlib para poder cambiar el comportamiento de la propiedad estática DateTime.Now. Para ello basta con pulsar botón derecho del ratón sobre el nodo References de nuestro proyecto y pulsar sobre “Add Moles Assembly for mscorlib”

Una vez hecho esto, vamos a escribir 2 pruebas unitarias:
- Sí el día de la semana es sábado, el resultado debe ser 20.
- Sí el día de la semana es otro cualquiera, el resultado debe ser 5.
/// <summary>This class contains parameterized unit tests for Discounts</summary>
[TestClass]
public class DiscountsTest
{
/// <summary>
/// Discount_s the must_ be_20_ if_ today_ is_ saturday.
/// </summary>
[TestMethod]
[HostType("Moles")]
public void Discount_Must_Be_20_If_Today_Is_Saturday()
{
//Arrange
MDateTime.NowGet = () => new DateTime(2011, 1, 15);
var discounts = new Discounts();
//Act
var discount = discounts.GetDiscount();
//Assert
Assert.AreEqual(discount, 20);
}
/// <summary>
/// Discount_s the must_ be_5_ if_ today_ is_ not_ saturday.
/// </summary>
[TestMethod]
[HostType("Moles")]
public void Discount_Must_Be_5_If_Today_Is_Not_Saturday()
{
//Arrange
MDateTime.NowGet = () => new DateTime(2011, 1, 21);
var discounts = new Discounts();
//Act
var discount = discounts.GetDiscount();
//Assert
Assert.AreEqual(discount, 5);
}
}
Al crear los moles de mscorlib, disponemos de un objeto MDateTime (Ya comentamos que las clases de Moles empiezan con el prefijo M y los Stubs con S) y mediante el uso del delegado NowGet, le decimos, que cuando en el ámbito de nuestro test unitario, en nuestro código se llame a la propiedad estática Now de la clase DateTime, siempre devuelva la fecha que nosstros le especificamos en nuestro delegado NowGet.
En el primer test el 15/01/2011 que fue el sábado pasado y en el segundo hoy (Viernes yeah!!!).
Si ejecutamos nuestros test:

Las pruebas unitarias pasan perfectamente!!!
Aquí es donde empezamos a ver la potencia que nos brinda este framework, aunque el ejemplo es muy simple, seguro que alguna vez nos hemos encontrado con código de este tipo, ya sea en APIS, librerías de terceros…
En la siguiente entrega veremos como hacer test unitarios a un FeatureReceiver de SharePoint.
Hasta entonces, feliz fin de semana a todos.