|
|
| Línea 1: |
Línea 1: |
| − | Mockito es una librería [[Java]] para la creación de [[Mock Object]] muy usados para el testeo unitario en [[Test Driven Development]], basado en [[EasyMock]].
| + | I'm relaly into it, thanks for this great stuff! |
| − | | |
| − | Mockito fue creado con el objetivo de simplificar y solucionar algunos de los temas antes mencionados. EasyMock y Mockito puede hacer exactamente las mismas cosas, pero Mockito tiene un API más natural y práctico de usar.
| |
| − | | |
| − | ==Características principales==
| |
| − | # Se pueden crear mocks de interfaces y clases concretas.
| |
| − | # Verificación de invocaciones (cantidad exacta, al menos una vez, órden de invocación, etc.)
| |
| − | # El stack trace se mantiene limpio, ya que los errores ocurren en los assert que se hagan (y no dentro del método bajo prueba, como en EasyMock).
| |
| − | # Un API más clara para crear stubs y verificaciones
| |
| − | | |
| − | ==Ejemplo de uso==
| |
| − | <code java>
| |
| − | import static org.mockito.Mockito.*;
| |
| − | .....
| |
| − | //creamos el mock y el stub
| |
| − | ArrayList instance = mock(ArrayList.class);
| |
| − | doReturn("hola mundo").when(instance).get(0);
| |
| − |
| |
| − | //ejecutamos la lógica a probar
| |
| − | instance.get(0);
| |
| − |
| |
| − | //verificamos que se hayan invocado los métodos
| |
| − | verify(instance).get(0);
| |
| − | </code>
| |
| − | | |
| − | ==Más de una invocación a un mismo método==
| |
| − | | |
| − | Algunas veces necesitamos que un método retorne un valor y que en la segunda invocación retorne nulo o una excepción. Para eso, anidamos los retornos:
| |
| − | | |
| − | <code html4strict>
| |
| − | | |
| − | //Retornos para las 2 invocaciones
| |
| − | doReturn("algo").doReturn(null).when(instance).scrollNext();
| |
| − | | |
| − | //ejecutamos la lógica a probar
| |
| − | instance.unMetodoQueUsaScroll();
| |
| − | | |
| − | //verificamos que se haya invocado el mismo método dos veces
| |
| − | verify(instance, times(2)).scrollNext();
| |
| − | | |
| − | </code>
| |
| − | | |
| − | * [http://mockito.googlecode.com/svn/branches/1.5/javadoc/org/mockito/Mockito.html Leer más en Mockito API]
| |
| − | | |
| − | ==Ejemplos de Mockito junto a PowerMock==
| |
| − | | |
| − | ===Invocación a un método estático===
| |
| − | | |
| − | Para mockear métodos estáticos, según el [http://code.google.com/p/mockito/wiki/FAQ FAQ] de mockito, esto no es posible. Pero nombra 2 framewors que pueden resultarnos útil [http://jmockit.dev.java.net/ JMockit] y [http://code.google.com/p/powermock PowerMock]
| |
| − | | |
| − | <code java>
| |
| − | @RunWith(PowerMockRunner.class)
| |
| − | @PrepareForTest(ClaseConMetodosEstaticos.class)
| |
| − | public class DosIdeasTestCase {
| |
| − | @Test
| |
| − | public void testMetodo_conInvocacionAMetodosEstaticos() {
| |
| − |
| |
| − | //PowerMockito mockea los metodos estaticos que se encuentren en la
| |
| − | //clase ClaseConMetodosEstaticos
| |
| − | PowerMockito.mockStatic(ClaseConMetodosEstaticos.class);
| |
| − | | |
| − | //Con mockito determinamos el retorno del metodo estatico
| |
| − | when(ClaseConMetodosEstaticos.firstStaticMethod(param)).thenReturn(value);
| |
| − | | |
| − | // ejecucion
| |
| − | instance.invocarMetodoEstatico();
| |
| − | | |
| − | //Por cada metodo estatico que se quiere verificar se debe invocar
| |
| − | //a PowerMockito.verifyStatic().
| |
| − | PowerMockito.verifyStatic();
| |
| − | ClaseConMetodosEstaticos.secondStaticMethod();
| |
| − | }
| |
| − | }
| |
| − | </code>
| |
| − | | |
| − | ===Invocación a un método privado===
| |
| − | | |
| − | <code java>
| |
| − | public class PruebaMetodoPrivado {
| |
| − | | |
| − | public String decirHola(String nombre) {
| |
| − | return decirHolaNombre(nombre);
| |
| − | }
| |
| − | | |
| − | private String decirHolaNombre(String nombre) {
| |
| − | return "Hola "+nombre;
| |
| − | }
| |
| − | }
| |
| − | </code>
| |
| − | | |
| − | <code java>
| |
| − | @RunWith(PowerMockRunner.class)
| |
| − | @PrepareForTest(PruebaMetodoPrivado.class)
| |
| − | public class PruebaMetodoPrivadoTest {
| |
| − | | |
| − | @Spy
| |
| − | PruebaMetodoPrivado metodoPrivado = new PruebaMetodoPrivado();
| |
| − |
| |
| − | @Test
| |
| − | public void mockMetodoPrivado() throws Exception {
| |
| − | | |
| − | Assert.assertEquals("Hola Juan", metodoPrivado.decirHola("Juan"));
| |
| − | doReturn("Chau Juan").when(metodoPrivado,"decirHolaNombre","Juan");
| |
| − | Assert.assertEquals("Chau Juan",metodoPrivado.decirHola("Juan"));
| |
| − | verifyPrivate(metodoPrivado,
| |
| − | Mockito.times(2)).invoke("decirHolaNombre","Juan");
| |
| − | }
| |
| − | }
| |
| − | | |
| − | </code>
| |
| − | | |
| − | ===Inicialización de atributos estaticos===
| |
| − | | |
| − | <code java>
| |
| − | public class PruebaInicializacionEstaticos {
| |
| − | | |
| − | private static final String atributo = new String("CHAU");
| |
| − |
| |
| − | public String crearObjetoLista() {
| |
| − | return atributo;
| |
| − | }
| |
| − | }
| |
| − | </code>
| |
| − | | |
| − | <code java>
| |
| − | @RunWith(PowerMockRunner.class)
| |
| − | @SuppressStaticInitializationFor("PruebaInicializacionEstaticos")
| |
| − | @PrepareForTest(PruebaInicializacionEstaticos.class)
| |
| − | public class PruebaMetodoPrivadoTest {
| |
| − |
| |
| − | | |
| − | PruebaInicializacionEstaticos pruebaInicializacionEstaticos =
| |
| − | new PruebaInicializacionEstaticos();
| |
| − |
| |
| − | @Test
| |
| − | public void controlCreacionLista() throws Exception {
| |
| − | Assert.assertNull(pruebaInicializacionEstaticos.retornarAtrinbuto());
| |
| − | String s = "Hola";
| |
| − | Whitebox.setInternalState(pruebaInicializacionEstaticos.class,"atributo", s);
| |
| − | Assert.assertEquals(s, pruebaInicializacionEstaticos.retornarAtrinbuto());
| |
| − | }
| |
| − | }
| |
| − | </code>
| |
| − | | |
| − | ===Captura creación de objetos===
| |
| − | | |
| − | <code java>
| |
| − | public class PruebaCreacionObjeto {
| |
| − |
| |
| − | public List crearObjetoLista() {
| |
| − | return new ArrayList();
| |
| − | }
| |
| − | }
| |
| − | </code>
| |
| − | | |
| − | <code java>
| |
| − | @RunWith(PowerMockRunner.class)
| |
| − | @PrepareForTest(PruebaCreacionObjeto.class)
| |
| − | public class PruebaMetodoPrivadoTest {
| |
| − |
| |
| − | @Spy
| |
| − | PruebaCreacionObjeto pruebaCreacionObjeto = new PruebaCreacionObjeto();
| |
| − |
| |
| − | @Test
| |
| − | public void controlCreacionLista() throws Exception {
| |
| − | List list = new ArrayList();
| |
| − | list.add("Hola");
| |
| − | whenNew(ArrayList.class).withNoArguments().thenReturn((ArrayList) list);
| |
| − | List resultado = pruebaCreacionObjeto.crearObjetoLista();
| |
| − | Assert.assertEquals(list, resultado);
| |
| − | verifyNew(ArrayList.class);
| |
| − | }
| |
| − | }
| |
| − | </code>
| |
| − | | |
| − | Para mas ejemplos de Mockito junto a PowerMock ver los [http://code.google.com/p/powermock/wiki/MockitoUsage13 ejemplos] provisto por la documentación de PowerMock.
| |
| − | | |
| − | [http://www.dosideas.com/descargas/category/3-testing.html?download=40 Descargar proyecto NetBeans demo de los ejemplos]
| |
| − | | |
| − | ===PowerMockito & Cobertura===
| |
| − | Existe un problema al utilizar PowerMockito con Cobertura (versión 1.8.4), este último no registra la corrida de los test con anotación @PrepareForTest, dando como resultados falta de cobertura.
| |
| − | Para solucionar este inconveniente solo hay que actualizar la versión de Cobertura.
| |
| − | | |
| − | ==Ejemplo de Mockito para mockear appender de log4j==
| |
| − | | |
| − | <code java>
| |
| − | //Inicializamos mock.
| |
| − | Appender mockAppender = mock(AppenderSkeleton.class);
| |
| − | //Inicializamos logger de la clase bajo test
| |
| − | Logger log = Logger.getLogger(ClaseATestear.class);
| |
| − | //Agregamos el mock del appender al logger.
| |
| − | log.addAppender(mockAppender);
| |
| − | //Seteamos el nivel de log que nos interesa recuperar.
| |
| − | log.setLevel(Level.DEBUG);
| |
| − | </code>
| |
| − | | |
| − | Para poder obtener los log que se produjeron utilizamos la clase ArgumentCaptor de mockito que nos permite, entre otras cosas, capturar los eventos de log.
| |
| − | | |
| − | <code java>
| |
| − | ArgumentCaptor loggingEventCaptor = ArgumentCaptor.forClass(LoggingEvent.class);
| |
| − | | |
| − | loggingEventCaptor.capture());
| |
| − | </code>
| |
| − | | |
| − | Una posible forma de obtener un mensaje particular es iterando la lista de mensajes que nos da la clase capturada.
| |
| − | | |
| − | <code java>
| |
| − | List<LoggingEvent> loggingEvent = (List<LoggingEvent>) loggingEventCaptor.getAllValues();
| |
| − | </code>
| |
| − | | |
| − | == BDDMockito ==
| |
| − | BDDMokcito es una clase alternativa que ofrece [[Mockito]] para crear pruebas al estilo [[Behavior Driven Development]] (BDD) (es decir, con bloques dado / cuando / entonces).
| |
| − | | |
| − | El problema es que el API de Mockito usa la palabra "when" y no se integra bien con los comentarios //given //when //then (según BDD, el stubbing forma parte del área //given, y no del //when).
| |
| − | | |
| − | BDDMockito agrega una clase que tiene alias para los métodos de stub, usando given(Object).
| |
| − | | |
| − | <code java5>
| |
| − | import static org.mockito.BDDMockito.*;
| |
| − |
| |
| − | Vendedor vendedor = mock(Vendedor.class);
| |
| − | Negocio negocio = new Negocio(vendedor);
| |
| − |
| |
| − | @Test
| |
| − | public void comprarPan() throws Exception {
| |
| − | //given
| |
| − | given(vendedor.buscarPan()).willReturn(new Pan());
| |
| − |
| |
| − | //when
| |
| − | Compra compra = negocio.comprarPan();
| |
| − |
| |
| − | //then
| |
| − | assertThat(compra, contienePan());
| |
| − | }
| |
| − | </code>
| |
| − | | |
| − | Stubbing con void y excepciones:
| |
| − | <code java5>
| |
| − | //given
| |
| − | willThrow(new RuntimeException("boo")).given(mock).foo();
| |
| − |
| |
| − | //when
| |
| − | Result result = sistemaBajoPrueba.ejecutar();
| |
| − |
| |
| − | //then
| |
| − | assertEquals(failure, result);
| |
| − | </code>
| |
| − | | |
| − | ==Ver también==
| |
| − | * [[EasyMock]]
| |
| − | * [[Captura De Parametros]]
| |
| − | * [[Inyeccion De Mocks De Mockito Con Spring]]
| |
| − | * [http://www.dosideas.com/descargas/category/3-testing.html?download=11%3Ademo-de-mockito Proyecto de ejemplos con Mockito]
| |
| − | * [http://www.dosideas.com/java/242-mockito-o-basta-de-easymock.html Introducción a Mockito]
| |
| − | * [http://mockito.googlecode.com/svn/branches/1.8.0/javadoc/org/mockito/BDDMockito.html Javadoc de BDDMockito]
| |
| − | | |
| − | [[Category:TDD]]
| |
| − | [[Category:BDD]]
| |
| − | [[Category:JUnit]]
| |