[Moles] Pruebas unitarias de código ASP.NET

En este post vamos a ver como podemos realizar pruebas unitarias sobre el framework de ASP.NET.

Antes de empezar quiero dejar claro que este código debe tomarse como un ejemplo para ver la potencia que nos brinda el framework de Moles.

Imaginaros que queremos hacer una prueba unitaria de este método:

public partial class CustomerInfo : System.Web.UI.Page

{

    /// <summary>

    /// Handles the Load event of the Page control.

    /// </summary>

    /// <param name="sender">The source of the event.</param>

    /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>

    public void Page_Load(object sender, EventArgs e)

    {

        var customer = Session["Customer"] as Customer;

 

        if (customer != null)

        {

            txtName.Text = customer.Name;

        }

    }

}

En nuestro test unitario, podemos declarar una variable del tipo CustomerInfo y llamar a su método Page_Load:

[TestMethod]

[HostType("Moles")]

public void When_Page_Loaded_TextBox_Name_ShouldBe_Equals_To_Customer_Name()

{

    var customerInfo = new CustomerInfo

                           {

                               txtName = new TextBox()

                           };

 

    // Act

    customerInfo.Page_Load(this, EventArgs.Empty);

    

 

    // Assert

    Assert.AreEqual(customerInfo.txtName.Text, "John");

}

Pero al ejecutar el test falla:

image

Si vemos los detalles del test:

image

Pues recibimos una excepción del tipo HttpExcepcion porque en el contexto de nuestro test unitario no tenemos disponible la Session, es decir, que el runtime de ASP.NET no lo tenemos disponible porque nuestros test unitarios no corren en IIS como si de una aplicación web se tratase.

¿Como podemos resolverlo?

Con el framework de Moles. Para ello vamos a crear los Moles de System.Web, para ello basta con pulsar el botón derecho del ratón sobre la dll System.Web y pulsar sobre “Add Moles Assembly”

image

Una vez hecho esto, vamos a empezar a componer nuestro test para que pase la prueba:

Como podemos observar en el error, estamos accediendo a la propiedad Session con la key Customer del objeto Page para obtener un objeto de tipo Customer (El objeto customer que en alguna parte de nuestra aplicación hemos guardado en la sesión).

Pues bien, vamos a emular este comportamiento con Moles (Porque decir Molear no queda bien)

// Arrange

var user = new Customer

{

    Name = "John",

};

 

MPage.Constructor = page =>

{

    new MPage(page)

    {

        SessionGet = () => new MHttpSessionState()

        {

            ItemGetString = (key) =>

            {

                Assert.AreEqual(key, "Customer");

                return user;

            }

        }

    };

};

Lo que estamos haciendo es decirle al framework de Moles es que cuando se cree un objeto del tipo Page y se llame a su propiedad Session[“Customer”] devuelva el usuario que hemos declarado más arriba.

Otra cosa que podemos hacer con moles, es usar Asserts en nuestro delegados, en mi caso compruebo que la key de la sessión que me están pasando es “Customer”

Todo este código se ejecutará cuando se llegue a la línea:

var customer = Session["Customer"] as Customer;

Si volvemos a ejecutar nuestro test, podemos comprobar que se ha ejecutado todo el código del método Page_Load porque nuestro textbox contiene el valor “John” que es lo que esperamos:

image

image

Espero que os haya gustado. Para la próxima SharePoint Smile

Un saludo.

[Gambadas] Facebook y la “Personalización instantánea”

Hoy he leido que Facebook entre hoy y mañana habilitará la Personalización instantánea dentro de la privacidad de tu cuenta, que entre otras cosas sino me equivoco, permite que empresas como Bing, TripAdvisor, Clicker, Rotten Tomatoes, Docs, Pandora, Yelp y Scribd tener acceso a la información que ya compartiste con todos (¿Y si solo la comparto con mis amigos?)

La cosa es que he ido a deshabilitar esta opción, puesto que por defecto viene habilitada y para ello he seguido estos pasos:

Cuanta –> Configuración de la privacidad

image

Editar tu configuración de Aplicaciones y sitios web

image

Personalización instantanea y pulsar sobre Editar la configuración

image

Leches!!! No lo han activado todavía…

image

No problem, vamos a hacer uso de las Developers Tools de IE a ver si funciona:

image

Pulsamos en la pestaña HTML y sobre la flechita y luego seleccionamos el check:

image

En la pestaña Attributtes podemos ver los atributos Html del check y como podemos observar está disabled. Seleccionamos el atributo disabled y pulsamos sobra la X

image

Y se nos habilita:

image

Lo desmarcamos y nos saldrá una ventanita como esta que nos vende la moto:

image

Luego saldrá la animación y se queda pillada, parace que no acaba nunca:

image

Pero si refrescamos la página o volvemos a entrar:

image

Tachan!!!

Un saludo.

[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”

image

Una vez hecho esto, vamos a escribir 2 pruebas unitarias:

  1. Sí el día de la semana es sábado, el resultado debe ser 20.
  2. 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:

image

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.

[Moles] Empezando con Stubs

Ya está empezando a hablarse sobre Moles en Geeks, el Bruno ha escrito un par de artículos un ejemplo sobre como utilizar Moles para realizar pruebas unitarias de Tasks en MSBuild y “Hola Mundo” con Moles y yo he escrito una pequeña introdución.

Ahora vamos a ver un ejemplo de Stubs, y para los que no sepan para que sirven o que son les refresco la memoria:

Stubs: Sirven para testear clases que implementan interfaces (Esto podría hacerse con otros frameworks de mock tales como Moq, RinhoMocks… ) y clases que no están selladas y que se pueden sobreescribir sus métodos.

Así que vamos a partir del siguiente ejemplo:

image

Un carrito de la compra en el que tenemos:

  • Entidades: Producto, Carrito y línea de carrito que tiene producto y cantidad.
  • Repositorios: El repositorio de productos.
  • Servicios: El servicio del carrito.

Al servicio del carrito solo le hemos añadido un método para añadir un producto al carrito y le hemos inyectado una dependencia al repositorio de productos:

public class ShoppingCartService

{

   /// <summary>

   /// IProductsRepository

   /// </summary>

   private IProductsRepository _productsRepository;

 

   /// <summary>

   /// Initializes a new instance of the <see cref="ShoppingCartService"/> class.

   /// </summary>

   /// <param name="productsRepository">The products repository.</param>

   public ShoppingCartService(IProductsRepository productsRepository)

   {

       _productsRepository = productsRepository;

   }

 

   /// <summary>

   /// Adds to cart.

   /// </summary>

   /// <param name="cart">The cart.</param>

   /// <param name="productId">The product id.</param>

   public void AddToCart(ShoppingCart cart, int productId)

   {

       var product = _productsRepository.Products.FirstOrDefault(p => p.ProductID == productId);

 

       if (product != null)

       {

           cart.AddItem(product, 1);

       }

   }

}

Para ahorrarnos trabajo, vamos a crear el proyecto de pruebas con Pex. Para ello con el botón derecho sobre el proyecto que queremos que nos genere los test y seleccionamos Pex –> Create Parametrized Unit Test

image

Con esto nos ahorramos generar los Moles y añadir todas las librerías que tenemos referenciadas en nuestro proyecto.

Elegimos el tipo de framework de pruebas que vamos a utilizar, en mi caso Visual Studio Unit Test (Tu puedes usar con el que estes más cómodo)

image

Y a continución, elegimos como queremos llamar a nuestro proyecto de tests y donde lo queremos guardar.

image

Una vez que pulsamos OK, Pex genera algo como esto:

image

Que limpiando las clases que no necesito y limpiando un poquito del código de la clase que testeará el servicio, quedará así:

image

Pues vamos a empezar a preparar el test unitario en el que vamos a testear que podemos añadir productos al carrito. Lo primero es hacer un mock del repositorio de productos y aquí es donde entran los Stubs:

//Arrange

var shoppingCart = new ShoppingCart();

 

var productsRepository = new SIProductsRepository()

{

    ProductsGet = () => new List<Product>

                            {

                                new Product { ProductID = 1 },

                                new Product { ProductID = 2 },

                                new Product { ProductID = 3 }

                            }.AsQueryable()

};

 

var shoppingCartService = new ShoppingCartService(productsRepository);

Como podéis observar, el Framework de Moles nos crea unos objetos que empiezan por S que corresponden con los Stubs y M que corresponden con los Moles, por lo tanto como mi repositorio implementará la interfaz IProductsRespository hago uso de Stubs SIProductsRespository

Una vez hecho esto, ejecutamos la acción que vamos a probar:

//Act

shoppingCartService.AddToCart(shoppingCart, 1);

Y por último comprobamos que tenemos una linea en el carrito y que la única línea que tenemos contiene el producto con ProductID = 1

//Assert

Assert.AreEqual(shoppingCart.Lines.Count, 1);

Assert.AreEqual(shoppingCart.Lines[0].Product.ProductID, 1);

Ejecutamos la prueba:

image

Esto mismo lo podíamos haber hecho con otro framework de Mocks tipo Moq:

var mockProductsRepos = new Mock<IProductsRepository>();

mockProductsRepos.Setup(x => x.Products).Returns(products.AsQueryable());

pero creo que así queda claro cuando debemos usar Stubs y que ademas podemos usarlo como framework de mocks para trabajar las pruenas unitarias junto con Pex.

En esta semana y si no tengo problemas técnicos, grabaré el vídeo sobre Stubs con este mismo ejemplo y se lo pasaré a la gente de MSDN para que lo cuelguen en Channel9.

En los siguientes post vamos a ver test unitarios sobre SharePoint, métodos no deterministas y propiedades estáticas como DateTime.Now usando Moles (También grabaré los vídeos).

Un saludo y espero que os resulte interesante.

PD: Adjunto el código de ejemplo.

[Moles]: Introducción

¿Qué es?

Para que nos entendamos, Moles es un framework de Stubs pero además nos permite testear clases selladas, métodos estáticos, no virtuales… mediante el uso delegados.

Para los que trabajan habitualmente con SharePoint y conocen TypeMock (De pago) a partir de ahora ya no hay excusa para hacer pruebas unitarias de receivers, features… de manera gratuita.

Diferencia entre Moles y Stubs

Dentro del framework de Moles tenemos:

Stubs: Para testear clases que implementan interfaces (Esto podría hacerse con otros frameworks de mock tales como Moq, RinhoMocks… ) y clases que no están selladas y que se pueden sobreescribir sus métodos.

Moles: Para testear clases selladas, estáticas y con métodos que no se pueden sobrescribir.

A continuación se muestra la tabla con las diferencias entre ambos:

Feature

Stub types

Mole types

Detour mechanism

Virtual method overriding

Runtime instrumentation

Static methods, sealed types

No

Yes

Internal types

Yes

Yes

Private methods

No

Yes

Static Constructors and Finalizers

No

Yes

Performance

Fast

Slower

Deployment

Xcopy

Installer

Abstract methods

Yes

No

 

¿Donde puedo descargarlo?

Moles se puede descargar junto con Pex o por separado como un Add-in de Visual Studio 2010.

http://research.microsoft.com/en-us/projects/pex/downloads.aspx

 

En el próximo post veremos cómo empezar a testear nuestro código con Stubs.

Habilitar el visor de documentos XPS en Windows Server 2008 R2

Esta mañana al abrir un documento XSP desde una VM me metí en un bucle infinito al darle a Open:

xpsalert

Para poder visualizar documentos XPS en Windows Server 2008 R2 tenemos que añadir una característica. Para ello abrimos el Server Manager

servermanager

Pulsamos en Add Feature:

xpsviewer

La instalamos y ya podemos visualizar documentos XPS.

Un saludo