Utilizar Rhino Mocks y StructureMap en pruebas unitarias con NUnit

26 nov. 2008
Rhino Mocks
En el posts anteriores ya vimos cómo utilizar y configurar StructureMap para poner en práctica la inyección de dependencias.

Tal y como prometí, ahora vamos a ver un pequeño ejemplo de cómo utilizar el StructureMap y el mocking de objetos en las pruebas unitarias.

Quizá te preguntes que es un “Mock”.

Un mock, en el contexto de pruebas unitarias, es un objeto “falso” que simula el comportamiento del objeto real, con el fin de realizar las pruebas. En la wikipedia lo asimilan al maniquí que utilizan los diseñadores coches para realizar las pruebas de accidentes.

Te sugiero si utilizas pruebas unitarias, profundices más sobre este tema.
Existen muchas librerías para realizar mocks en .NET.

En el ejemplo que voy a plantear utilizaré Rhino Mocks, para crear un mock de un servicio de mensajería, ya que no quiero que realmente se envíe el correo electrónico al usuario, simplemente quiero probar que el método se llama convenientemente.

Primero crearé la interfaz de este servicio de mensajería.

    1 public interface IMessagingService

    2 {

    3     void SendMessage(User user, string text);

    4 }



En la aplicación “real”, no en las pruebas unitarias, configuraré StructureMap para que el servicio de mensajería sea una implementación de esta interfaz para enviar correos electrónicos. Pero podría ser cualquier otra cosa, enviar SMS, un texto al Messenger, etc…

    1 private static void ConfigureStructureMap()

    2 {

    3     ObjectFactory.Configure(s =>

    4         s.BuildInstancesOf<IMessagingService>()

    5         .TheDefaultIsConcreteType<EmailMessagingService>());

    6 }



El controlador de asp.net mvc que queremos probar tiene la siguiente acción:
 

    1 public ActionResult CreateUser(string userName, string password, string email)

    2 {

    3     User user = new User{UserName = userName, Password = password, Email = email};

    4 

    5     UserValidationResult result = userService.Register(user);

    6 

    7     if (result.IsValid)

    8     {

    9         IMessagingService messagingService = ObjectFactory.GetInstance<IMessagingService>();

   10 

   11         messagingService.SendMessage(user, "Tu cuenta ha sido creada correctamente");

   12 

   13         return Authenticate(userName, password, null);

   14     }

   15 

   16     TempData["RegisterErrors"] = result.Errors;

   17 

   18     return RedirectToAction("Register");

   19 }


Y ahora en las pruebas unitarias, comprobaremos que el método SendMessage se llama al crear un nuevo usuario. Utilizaremos NUnit como librería de pruebas y habrá que añadir la referencia al dll de Rhino Mocks de y de StructureMap al proyecto de pruebas.

    1 [Test]

    2 public void CreateUser_Creates_Users_And_Sends_Email()

    3 {

    4     MockRepository mocker = new MockRepository();

    5 

    6     IMessagingService messagingService = mocker.StrictMock<IMessagingService>();

    7 

    8     Expect.Call(() => messagingService.SendMessage(null, null))

    9         .IgnoreArguments();

   10 

   11     mocker.ReplayAll();

   12 

   13     ObjectFactory.Inject(messagingService);

   14 

   15     controller.CreateUser("usuario", "clave", "direccion@correo.es");

   16 

   17     mocker.VerifyAll();

   18 }



Veamos con más detalle el código de esta prueba.

En la línea 1 le indico a NUnit que este método es una prueba.

En la línea 4 creamos el objeto de Rhino Mocks que se encargará de generar los objectos Mocks a partir de la definición de la interfaz.

En la línea 6 creamos obtenemos la implementación simulada del servicio IMessagingService.

En la líneas 8 y 9, le decimos a Rhino Mocks que esperamos que en el futuro se llame al método SendMessage del objeto messagingService y que nos dan igual los argumentos utilizados. El método Expect.Call espera como parámetro un delegado que se lo hemos pasado utilizando una expressión lambda.

En la línea 12, le indicamos al objeto MockRepository que ya hemos fijado todas las expectativas (en nuestro caso, sólo la establecida en la línea 8) y que vamos a empezar las pruebas.

En la línea 13, inyectamos la interfaz simulada a StructureMap para que utilice este objeto, en vez de lo que tenga en su configuración.

En la línea 14, llamamos al objeto que estamos probando con algunos parámetros por defecto.

En la línea 15, le pedimos a Rhino Mocks, que verifique que se han cumplido todas las expectativas establecidas. En nuestro caso queríamos que se llamara al método SendMessage al crear un usuario. Si esto no ocurriera, este método lanzaría una excepción por lo que la prueba unitaria no se pasaría correctamente.

¡Espero que te haya servido de ayuda!
comments powered by Disqus
subir