Este documento introduce el uso de objetos Mock en pruebas unitarias. Explica que Mockito es un framework que permite generar objetos Mock de forma dinámica para simular dependencias. Detalla algunas funciones de Mockito como la verificación de comportamientos, programación de comportamientos, comparación de argumentos, y verificación del número de invocaciones. Finalmente, muestra un ejemplo práctico de integración de Mockito con JUnit y NetBeans para realizar un test unitario.
Este documento introduce el uso de objetos Mock en pruebas unitarias. Explica que Mockito es un framework que permite generar objetos Mock de forma dinámica para simular dependencias. Detalla algunas funciones de Mockito como la verificación de comportamientos, programación de comportamientos, comparación de argumentos, y verificación del número de invocaciones. Finalmente, muestra un ejemplo práctico de integración de Mockito con JUnit y NetBeans para realizar un test unitario.
Este documento introduce el uso de objetos Mock en pruebas unitarias. Explica que Mockito es un framework que permite generar objetos Mock de forma dinámica para simular dependencias. Detalla algunas funciones de Mockito como la verificación de comportamientos, programación de comportamientos, comparación de argumentos, y verificación del número de invocaciones. Finalmente, muestra un ejemplo práctico de integración de Mockito con JUnit y NetBeans para realizar un test unitario.
Facultad Regional Mendoza UTN - Tecnicatura Superior en Programacin Laboratorio de Computacin II Profesor: Ing. Julio Monetti Alumnos: Leandro Alfredo Nafissi | Legajo #36771 Guillermo Baker | Legajo # 36805
Turno Maana - Ciclo Lectivo 2012 Objetos Mock
Objetivos 1 Objetivos Este trabajo tiene por objetivos: Introducir al programador en el uso de objetos Mock.
Describir y mostrar el uso de objetos Mock como herramientas en la realizacin de pruebas unitarias.
Documentar el uso y funcionamiento del Framework Mockito, junto con los pasos necesarios para su integracin en NetBeans IDE 7.1.
Describir los pasos necesarios para realizar un simple test unitario, usando JUnit y el framework Mockito en NetBeans IDE 7.1.
Objetos Mock
Objetivos 2 Contenido Objetivos ...................................................................................................................................... 1 Objetos Mock .............................................................................................................................. 3 Introduccin ................................................................................................................................ 3 Qu es un Mock? ................................................................................................................... 3 Qu es Mockito? ..................................................................................................................... 3 Pruebas Unitarias y el uso de Objetos Mock .......................................................................... 4 Por qu usar Mockito? .......................................................................................................... 5 Cmo se usa Mockito? ........................................................................................................... 5 Qu se puede hacer con Mockito?. ...................................................................................... 5 1. Verificacin de comportamientos o acciones ......................................................... 6 2. Stubbing (Programacin de comportamientos) ..................................................... 6 3. Argument Matchers (Comparacin de Argumentos) ........................................... 7 4. Verificacin del nmero exacto de invocaciones, al menos X, o ninguna invocacin ............................................................................................................................ 7 5. Stubbing de metodos void con excepciones ........................................................... 8 6. Verificaciones en orden ............................................................................................. 8 7. Asegurndonos de que nunca ocurran una o varias interacciones en un Mock9 8. Buscando Invocaciones Redundantes ..................................................................... 9 9. Abreviatura en la creacin de Mocks La Anotacin @Mock ........................... 10 Experiencia Prctica: Mockito + JUnit + NetBeans 7.1 ........................................................ 11 Descarga e Instalacin de Mockito en NetBeans IDE 7.1 ................................................ 11 Verificacin: Test Unitario de Prueba ................................................................................ 15 Conclusiones ............................................................................................................................. 19 Bibliografa ................................................................................................................................ 20 Mockito API Documentation .......................................................................................... 20 Mock Aren't Stubs ............................................................................................................ 20 Effective Mockito (Part 1, Part 2, Part 3, Part 4, Part 5) ............................................... 20 Using Mockito to Unit Test Java Applications ............................................................. 20 Mockito in six easy examples ......................................................................................... 20 JUnit, Mock Objects, and More ...................................................................................... 20 CODIGOS FUENTES UTILIZADOS COMO REFERENCIA .................................... 20 Objetos Mock
Introduccin 3 Objetos Mock Uso de Objetos Mock en pruebas unitarias. Introduccin Para poder crear un buen conjunto de pruebas unitarias, es necesario centrarnos exclusivamente en la clase a probar, simulando el funcionamiento de las capas inferiores. De esta manera estaremos creando pruebas unitarias robustas y confiables, que nos permitiran detectar y solucionar errores que tengamos o que se cometan a futuro durante el desarrollo de nuestra aplicacin. Para esta tarea nos apoyaremos en el uso de objetos Mock, que no son ms que objetos que simulan parte del comportamiento de una clase, y ms especficamente vamos a ver una herramienta llamada Mockito, que nos permite generar objetos Mock y trabajar con ellos en forma dinmica. Qu es un Mock? Un objeto mock es un reemplazo (orientado a pruebas) de un colaborador (objeto original imitado). El objeto mock es programado para simular al objeto que reemplaza de una manera simple. Este objeto simulador debe de ser provisto a la clase a probar para que sta haga uso de l, durante el test de prueba, como si hiciera uso de los objetos dependientes externos originales. Qu es ? Mockito es un framework basado en EasyMock que nos permite generar objetos mock y trabajar con ellos en forma dinmica.
Mockito incorpora muchas mejoras en la sintaxis del API de EasyMock, hacindola ms entendible e intuitiva de usar.
A diferencia de muchas otras libreras, Mockito permite crear objetos mock (o mocks) de clases concretas (y no slo de interfaces). Los mocks de Mockito no son slo stubs. Objetos Mock
En trminos de programacin los Objetos Mock son objetos simuladores, usados para imitar a otros objetos, con sus mismos atributos, mtodos, y comportamientos.
Mockito es un mocking framework basado en EasyMock que nos permite generar objetos simuladores de forma dinmica. Mockito puede integrarse en IDEs tales como NetBeans o Eclipse y ser usado en conjunto con JUnit. Objetos Mock
Pruebas Unitarias y el uso de Objetos Mock 4
Orgenes de Szczepan Faber comenz con el proyecto de Mockito luego de encontrarse con que los frameworks que existan en ese momento para trabajar con objetos Mocks eran muy complejos y complicados. Su meta era crear un nuevo marco de trabajo que fuera ms sencillo para usar, y obteniendo mejores resultados. Szczepan empez por expandir la misma sintaxis y funcionalidad de Easy Mock, pero eventualmente tuvo que re-escribir gran parte de Mockito. Las primeras versiones del proyecto Mockito aparecen a principios del 2008 en Londres. Pruebas Unitarias y el uso de Objetos Mock
Por qu y cundo usar Objetos Mock? Un problema comn que enfrentamos cuando realizamos pruebas unitarias es como probar un objeto que depende de otro objeto. Podramos crear instancias tanto del objeto bajo prueba como del objeto dependiente, pero el testeo con objetos agregados ya deja de ser un test unitario. Idealmente, un test unitario debera probar objetos individuales y comprobar si el comportamiento del objeto es correcto, sin la agregacin de otros objetos, o al menos con la menor interferencia posible de objetos externos. Por otra parte, este enfoque no funcionar si el objeto dependiente an no ha sido implementado. Una tcnica comn para el manejo de las dependencias en las pruebas unitarias es proporcionar un sustituto, o un objeto mock", para el objeto dependiente en lugar de uno real. En esta tcnica, tambin conocida como Mocking, el objeto mock implementa una versin simplificada de los mtodos de los objetos reales, que devuelven resultados predecibles y pueden ser utilizados para propsitos de prueba.
Objetos Mock
Pruebas Unitarias y el uso de Objetos Mock 5
El inconveniente de este enfoque es que en una aplicacin compleja podramos encontrarnos en la creacin de una gran cantidad de objetos mock. Es en casos como estos donde un mocking framework, como Mockito, nos puede ahorrar mucho tiempo y esfuerzo.
Por qu usar ? Una de las razones principales por las que se decidi usar Mockito es la simpleza que presenta en su sintaxis. En comparacin con otros mocking framework, Mockito presenta una sintaxis intuitiva y fcil de comprender. La API de Mockito se encuentra adems muy bien documentada. Se lo puede implementar en cualquier proyecto Java de manera relativamente sencilla dado que solo debemos importar un paquete .jar a nuestro proyecto para su uso. Adems, presenta la posibilidad de integrarse muy bien con JUnit para ser usado en conjunto en entornos de desarrollo populares tales como Eclipse, o NetBeans. Ms adelante veremos cmo integrar el framework con el IDE NetBeans. La integracin con Eclipse es muy similar. Cmo se usa ? La manera de realizar pruebas con Mockito se basa en tres conceptos: Stubbing: programar un comportamiento. Ejecutar: ejecutar las llamadas. Verificar: verificar las llamadas. Los esfuerzos se centran no slo en los resultados obtenidos por los mtodos a probar, sino tambin en la interaccin entre las clases bajo prueba y las clases de apoyo. Las clases de apoyos son aquellas que sern mockeadas, esto es, los mocks a crear imitaran el comportamiento de dichas clases de apoyo. Qu se puede hacer con ? A continuacin describiremos slo algunas de las funcionalidades de Mockito. Para comprender el API de Mockito con mayor facilidad, se har uso de ejemplos que realizarn mocks sobre listas (List), simplemente porque la interfaz List es muy conocida (se usaran mtodos cmo add(), get(), clear()).
Verificar Acciones o Comportamientos verify(mocked.accion) Objetos Mock
Pruebas Unitarias y el uso de Objetos Mock 6 1. Verificacin de comportamientos o acciones
Una vez creado, el mock recordar todas las interacciones. Luego podemos verificar selectivamente cualquier interaccin que nos interese. 2. Stubbing (Programacin de comportamientos)
El stubbing consiste en simular el comportamiento de un cdigo existente. En nuestro caso, consiste en simular el comportamiento de una clase (objeto), esto es, con sus mtodos, atributos, etc. Por defecto, todos los mtodos que devuelven valores y que son operados por un mock devuelven: null, una coleccin vaca o el tipo de dato primitivo apropiado.
La opcin when().thenReturn(); nos permite programar el comportamiento de los mocks. Por ejemplo si queremos simular un ArrayList a travs de un mock, entonces podramos indicarle qu valor deber devolver un get(index) cuando esta accin sea llevada a cabo. Esto nos permite, emular el comportamiento de los mtodos para los fines de un test especfico, o cuando se codifica y se necesita interactuar con algn colaborador del cual no se dispone. //creamos un mock de una lista List mockedList = mock(List.class); //usando el objeto mock mockedList.add("uno"); // simulo la accion add() mockedList.clear(); // simula la accion clear() //verificacin verify(mockedList).add("uno"); verify(mockedList).clear();
// Podemos hacer Mokcs de clases concretas, no solo interfaces LinkedList mockedList = mock(LinkedList.class);
// lanza una runtime exception System.out.println(mockedList.get(1));
//imprime "null" por que get(999) no fu programado System.out.println(mockedList.get(999));
Objetos Mock
Pruebas Unitarias y el uso de Objetos Mock 7 3. Argument Matchers (Comparacin de Argumentos) Mockito verifica los valores de los argumentos con el estilo natural de java, usando el mtodo equals(). En ocasiones, cuando se requiere de una flexibilidad extra, entonces podramos usar argument matchers. Los arguments matchers permiten realizar llamadas a mtodos mediante comodines, de manera que los parmetros a los mismos no se tengan que definir explcitamente. Los argument matchers permiten realizar stubbing y verificaciones muy flexibles.
Ms informacin en: http://Mockito.googlecode.com/svn/branches/1.7/javadoc/org/Mockito/Matchers.html 4. Verificacin del nmero exacto de invocaciones, al menos X, o ninguna invocacin
Ejemplo de cmo verificar si se ha un cumplido un nmero mnimo o mximo de llamadas al mock.
//stubbing usando hamcrest (libreria de matchers) (digamos que isValid() devuelve tu propio matcher) when(mockedList.contains(argThat(isValid()))) .thenReturn("elemento");
//las dos verificaciones siguientes trabajan de la misma //manera (times(1) se usa por defecto) verify(mockedList).add("once"); verify(mockedList, times(1)).add("once"); Objetos Mock
Pruebas Unitarias y el uso de Objetos Mock 8
5. Stubbing de metodos void con excepciones Ejemplo de cmo realizar stubbing de mtodos que no devuelven nada (por ejemplo para indicar que deben lanzar una excepcin):
6. Verificaciones en orden Si necesitamos que varios mock necesiten llevar un orden especfico en las llamadas lo podemos verificar de la siguiente manera:
//verificacion de numero exacto de invocaciones verify(mockedList, times(2)).add("twice"); verify(mockedList, times(3)).add("three times"); //verificacion utilizando never. never(), un alias de //times(0) verify(mockedList, never()).add("never happened"); //verificacion utilizando atLeast()/atMost() verify(mockedList, atLeastOnce()).add("three times"); verify(mockedList, atLeast(2)).add("five times"); verify(mockedList, atMost(5)).add("three times");
// A. Single mock whose methods must be invoked in a // particular order List singleMock = mock(List.class);
//using a single mock singleMock.add("was added first"); singleMock.add("was added second");
//create an inOrder verifier for a single mock InOrder inOrder = inOrder(singleMock);
//following will make sure that add is first called with // "was added first, then with "was added second" inOrder.verify(singleMock).add("was added first"); inOrder.verify(singleMock).add("was added second");
Objetos Mock
Pruebas Unitarias y el uso de Objetos Mock 9
Realizar verificaciones en orden es muy flexible. No es necesario verificar todas las interacciones, sino slo aquellas que necesitamos. 7. Asegurndonos de que nunca ocurran una o varias interacciones en un Mock
8. Buscando Invocaciones Redundantes
// B. Multiple mocks that must be used in a particular // order List firstMock = mock(List.class); List secondMock = mock(List.class);
//using mocks firstMock.add("was called first"); secondMock.add("was called second");
//create inOrder object passing any mocks that need to // be verified in order InOrder inOrder = inOrder(firstMock, secondMock);
//following will make sure that firstMock was called //before secondMock inOrder.verify(firstMock).add("was called first"); inOrder.verify(secondMock).add("was called second");
// Oh, and A + B can be mixed together at will
//using mocks - only mockOne is interacted mockOne.add("one");
//following verification will fail verifyNoMoreInteractions(mockedList); Objetos Mock
Pruebas Unitarias y el uso de Objetos Mock 10 A word of warning: Some users who did a lot of classic, expect-run-verify Mocking tend to use verifyNoMoreInteractions() very often, even in every test method. verifyNoMoreInteractions() is not recommended to use in every test method. verifyNoMoreInteractions() is a handy assertion from the interaction testing toolkit. Use it only when it's relevant. Abusing it leads to overspecified, less maintainable tests. You can find further reading here. See also never() - it is more explicit and communicates the intent well. 9. Abreviatura en la creacin de Mocks La Anotacin @Mock Minimiza la creacin repetitiva de cdigo mock. Hace a la clase Test ms legible. Hace la verificacin de errores ms fcil de leer porqu el nombre del campo es usado para identificar el mock.
Importante! La siguiente llamada debe encontrarse en algn lugar de una clase base o del test runner: MockitoAnnotations.initMocks(testClass); Tambin se pueden usar built-in runners como: MockitoJUnitRunner, MockitoJUnit44Runner.
El API de Mockito provee muchas ms funcionalidades que se encuentran muy bien documentadas en el Sitio Web oficial de Mockito: http://docs.Mockito.googlecode.com/hg/latest/org/Mockito/Mockito.html
A continuacin se describen los pasos necesarios para integrar Mockito en NetBeans y probar su funcionamiento junto con JUnit, a travs de un test unitario simple de prueba.
Descarga e Instalacin de Mockito en NetBeans IDE 7.1 1. Primero nos dirigimos al sitio Web oficial del proyecto Mockito: http://code.google.com/p/Mockito/
2. En la seccin Downloads (en: http://code.google.com/p/Mockito/downloads/list) elegimos y descargamos de la lista una versin estable de Mockito. Durante la realizacin de este trabajo se utiliz el paquete: Mockito-all-1.9.0.jar.
Objetos Mock
Experiencia Prctica: Mockito + JUnit + NetBeans 7.1 12 3. Ejecutamos el IDE NetBeans 7.1.
4. Creamos un nuevo proyecto (le damos un nombre, por ejemplo: holaMockito).
5. Importamos el paquete Mockito-all-1.9.0.jar a nuestro proyecto. a. En la ventana de proyectos expandimos el contenido de nuestro proyecto, haciendo clic sobre el signo (+) que posee el cono de la taza de caf. Luego hacemos clic con el botn derecho sobre la carpeta Libraries y seleccionamos la opcin Add JAR/Folder en el men emergente.
b. A continuacin buscamos el paquete descargado Mockito-all-1.9.0.jar. Una vez encontrado hacemos doble clic sobre l o presionamos el botn Open para finalmente importarlo al proyecto. Objetos Mock
c. Luego comprobamos que el paquete .jar se haya importado exitosamente. Para ello verificamos el contenido de la carpeta Libraries de nuestro proyecto, en la ventana de proyectos.
Objetos Mock
Experiencia Prctica: Mockito + JUnit + NetBeans 7.1 15 Verificacin: Test Unitario de Prueba
Con el fin de verificar el correcto funcionamiento del Framework Mockito, se crearon dos simples clases: una Interfaz llamada ITraductor y otra clase llamada Saludo. Luego se gener un JUnit Test para la clase Saludo y se agreg un simple cdigo, basado en Mockito, en la Clase Test generada. Finalmente se compil y ejecut la prueba unitaria.
El ejemplo realizar una prueba unitaria de la clase Saludo. Dicha clase utiliza un mtodo de la clase interfaz ITraductor. A fin de poder aislar a la clase bajo prueba (Saludo) se creara un objeto mock que simular el comportamiento de la clase Interfaz, ITraductor, para que ste cumpla el papel de suplirle a la clase Saludo el mtodo que sta requiere para su funcionamiento y que adems se desea probar. A continuacin los pasos que se siguieron: 1. Creamos en nuestro proyecto una interface llamada ITraductor
2. Creamos la clase Saludo
1 package saludos; 2 3 public interface ITraductor { 4 //: Definimos un metodo abstracto para la interfaz 5 public abstract String traducirDeInglesA(String 6 palabra, String toIdiom); 7 8 }
1 package saludos; 2 3 public class Saludo { 4 private ITraductor traductor; 5 6 //: Constructor sobrecargado 7 public Saludo(ITraductor traductor) { 8 this.traductor = traductor; 9 } 10 11 //: Metodo 12 public String decirHola(String idioma, String nombre) { 13 String d = traductor.traducirdeInglesA("Hello", idioma); 14 15 return d + " " + nombre; 16 17 } 18 }
Objetos Mock
Experiencia Prctica: Mockito + JUnit + NetBeans 7.1 16 3. Creamos un JUnit Test para probar la clase Saludo
4. Seleccionamos a continuacin la versin de JUnit con la que deseamos crear el test y elegimos las opciones extras a incluir en el cdigo de la Clase Test a generar.
5. NetBeans crea automticamente la carpeta Test Packages, dentro de la cual coloca la Clase Test generada por jUnit (SaludoTest.java). Esta nueva clase generada ser (un caso de prueba) la que usaremos para probar la clase Saludo.
En su interior deberemos agregar los siguientes imports en el encabezado: import org.junit.*; import static org.mockito.Mockito.*; import static org.junit.Assert.*; import org.junit.Test;
Objetos Mock
Experiencia Prctica: Mockito + JUnit + NetBeans 7.1 18 6. Luego, hacemos doble clic sobre la clase de prueba generada para abrirla en el editor, y dentro del mtodo que se encuentra a continuacin de la etiqueta @Test, agregamos un pequeo cdigo basado en Mockito para probar el correcto funcionamiento del Framework.
Ejemplo de los resultados del Test: Test Passed 100%
Es posible trabajar en conjunto con las opciones que nos ofrece JUnit para hacer testing, sin interferencia alguna con el framework Mockito. Es decir, es posible por ejemplo, usar aserciones (assertEqual()) y al mismo tiempo utilizar los mtodo que provee mockito (when(), verify(), etc) para iteractuar con los mocks generados durante una prueba. Conclusiones Durante la realizacin de este trabajo no se pudo encontrar documentacin sobre el uso de objetos mocks en pruebas unitarias, en particular con el uso del framework Mockito, y en conjunto con el uso de JUnit y el IDE NetBeans. As mismo, encontrar informacin en castellano result ser una ardua tarea. Fu curioso observar, que la poca informacin que se encuentra disponible esta soportada por usuarios del IDE Eclipse. Este trabajo no slo nos permiti cubrir dicho vaco, sino tambin obtener resultados muy satisfactorios, que intentan ser reproducibles y de gran utilidad para los programadores de habla hispana. El uso de objetos mock es una herramienta muy valiosa, que nos facilita enormemente la elaboracin de pruebas unitarias de software. La facilidad de uso y todas las funcionalidades que ofrece en particular el mocking framework Mockito hace del uso de objetos mock una herramienta mucho ms atractiva an. Fueron rpidamente notadas las mejoras que este framework trae sobre su antecesor de base, Easy Mock. En principio se intent utilizar EasyMock como sistema de mocking para la elaboracin de este trabajo. A pesar de cumplir con las expectativas y obtener resultados robustos con el uso de Easy Mock, pudimos comprobar el porqu del origen de Mockito. EasyMock result ser bastante engorroso y confuso en su sintaxis y es por ello decidimos cambiar a Mockito, el cual mejora notablemente esta falencia, adems de ofrecer una gran flexibilidad y fcil implementacin. El cambio fue ms que satisfactorio. El hecho de poder combinar su uso en conjunto con las herramientas que ofrece JUnit permite obtener y evaluar una gran cantidad de resultados de test, haciendo que una prueba se vuelva mucho ms robusta. JUnit y Mockito, trabajando en conjunto, se potencian mutuamente. Encontramos que Mockito no slo es una herramienta muy valiosa y til en la realizacin de pruebas unitarias, sino tambin un excelente soporte para el programador durante el desarrollo de cdigo en general. Nos permite, entre muchas otras cosas, auto abastecernos de dependencias de uso rpido que sin la participacin de otros programadores y sin la disponibilidad de tiempo extra, seran muy difciles de implementar en forma confiable, automatizable, y controlable. Objetos Mock
Bibliografa 20 Bibliografa
Mockito API Documentation http://docs.Mockito.googlecode.com/hg/latest/org/Mockito/Mockito.html Mock Aren't Stubs http://martinfowler.com/articles/MocksArentStubs.html Effective Mockito (Part 1, Part 2, Part 3, Part 4, Part 5) http://eclipsesource.com/blogs/2011/09/19/effective-Mockito-part-1/ Using Mockito to Unit Test Java Applications http://blog.smartkey.co.uk/2010/02/Mockito-unit-test-java/
Mockito in six easy examples http://gojko.net/2009/10/23/Mockito-in-six-easy-examples/ JUnit, Mock Objects, and More http://mf9it.wordpress.com/2009/09/23/junit-Mock-objects-and-more/
CODIGOS FUENTES UTILIZADOS COMO REFERENCIA Algunos de los cdigos fuente utilizados en este trabajo fueron creados, modificados y readaptados tomando como referencia cdigos fuentes publicados en la Web: Mockito.LoginServiceExample http://schuchert.wikispaces.com/Mockito.LoginServiceExample