workshop - pruebas unitarias (con java)

22
Workshop Tema: Pruebas unitarias Autores Luciano Martinez Andrés Sommariva Fecha Marzo 2013 Versión: 1.0 1 de 22

Upload: microgestion

Post on 12-Jul-2015

2.245 views

Category:

Technology


3 download

TRANSCRIPT

Page 1: Workshop - Pruebas Unitarias (con Java)

Workshop

Tema: Pruebas unitarias

Autores Luciano Martinez Andrés Sommariva

Fecha Marzo 2013

Versión: 1.0

1 de 22

Page 2: Workshop - Pruebas Unitarias (con Java)

Índice

Teoría¿Por qué pruebas unitarias?IntroducciónCaracterísticasVentajasDesventajasLimitacionesPruebas Mock (Definición general)mockConcepto de stub, mock y proxy

Ejemplo Stub (pseudocódigo)Ejemplo Mock (pseudocódigo)

EstrategiasClases de IO

EjemplosClases de acceso a base de datos

EjemploClases dependientes de un “Servlet Container”Pruebas en “Dependency Injection Container”Spring FormAction

EjemploSpring Validator

EjemploSpring Web Flow flows

Java ­ Introducción a los frameworksJUnit

EjemploAssert statementsCrear una suite de pruebas con JUnit

PrácticaEvaluaciónReferencias / Links útiles

2 de 22

Page 3: Workshop - Pruebas Unitarias (con Java)

Pruebas unitariasTeoría

¿Por qué pruebas unitarias?Todos los programadores saben que deben realizar pruebas a su código. Pocos lo hacen.La respuesta generalizada al “¿por qué no?” es “No tengo tiempo”. Este apuro se convierteen un círculo vicioso. Cuanta más presión se siente, menos pruebas se realizan. Cuantasmenos pruebas se realizan, menos productivo se es y el código se vuelve menos estable.Cuanto menos productivo y preciso se es, más presión se siente.

IntroducciónUn unit test es un método que prueba una unidad de código. Al hablar de una unidad decódigo nos referimos a un requerimiento. Muchos desarrolladores tienen su propio conceptode lo que es una prueba unitaria; sin embargo, la gran mayoría coincide en que una pruebaunitaria tiene las siguientes características:

Prueba solamente pequeñas cantidades de código: Solamente prueba el código delrequerimiento específico.

Se aísla de otro código y de otros desarrolladores: El unit test prueba exclusivamenteel código relacionado con el requerimiento y no interfiere con el trabajo hecho porotros desarrolladores.

Solamente se prueban los endpoints públicos: Esto principalmente porque losdisparadores de los métodos privados son métodos públicos por lo tanto se abarcael código de los métodos privados dentro de las pruebas.

Los resultados son automatizados: Cuando ejecutamos las pruebas lo podemoshacer de forma individual o de forma grupal. Estas pruebas las hace el motor deprueba y los resultados de los mismos deben de ser precisos con respecto a cadaprueba unitaria desarrollada

Repetible y predecible: No importa el orden y las veces que se repita la prueba, elresultado siempre debe de ser el mismo.

Son rápidos de desarrollar: Contrariamente a lo que piensan los desarrolladores –>que el desarrollo de pruebas unitarias quita tiempo – los unit test por lo general debende ser simples y rápidos de desarrollar. Difícilmente una prueba unitaria deba detomar más de cinco minutos en su desarrollo.

3 de 22

Page 4: Workshop - Pruebas Unitarias (con Java)

CaracterísticasPara que una prueba unitaria sea buena debe cumplir los siguientes requisitos:

Automatizable: No debería requerirse una intervención manual. Esto esespecialmente útil para integración continua.

Completas: Deben cubrir la mayor cantidad de código. Repetibles o Reutilizables: No se deben crear pruebas que sólo puedan ser

ejecutadas una sola vez. También es útil para integración continua. Independientes: La ejecución de una prueba no debe afectar a la ejecución de otra. Profesionales: Las pruebas deben ser consideradas igual que el código, con la

misma profesionalidad, documentación, etc.

VentajasEl objetivo de las pruebas unitarias es aislar cada parte del programa y mostrar que laspartes individuales son correctas. Proporcionan un contrato escrito que el trozo de códigodebe satisfacer. Estas pruebas aisladas proporcionan cinco ventajas básicas:

Fomentan el cambioLas pruebas unitarias facilitan que el programador cambie el código para mejorar suestructura (lo que se ha dado en llamar refactorización), puesto que permiten hacerpruebas sobre los cambios y así asegurarse de que los nuevos cambios no hanintroducido errores.

Simplifica la integraciónPuesto que permiten llegar a la fase de integración con un grado alto de seguridad deque el código está funcionando correctamente. De esta manera se facilitan laspruebas de integración.

Documenta el códigoLas propias pruebas son documentación del código puesto que ahí se puede vercómo utilizarlo.

Separación de la interfaz y la implementaciónDado que la única interacción entre los casos de prueba y las unidades bajo pruebason las interfaces de estas últimas, se puede cambiar cualquiera de los dos sinafectar al otro, a veces usando objetos mock (mock object) para simular elcomportamiento de objetos complejos.

Los errores están más acotados y son más fáciles de localizarDado que tenemos pruebas unitarias que pueden desenmascararlos.

Mejoran el diseñoEn prácticas como Test Driven Development (TDD) permiten plantear elcomportamiento esperado en un paso previo a la codificación.

Puede ser la forma más simple de verificar el funcionamientoEn situaciones como el desarrollo de una API o un componente que brinda serviciosdel cual no se cuenta aún con un cliente para consumirlos.

4 de 22

Page 5: Workshop - Pruebas Unitarias (con Java)

DesventajasEl desarrollo de los casos de prueba unitarios puede ser percibido como una pérdida detiempo dado que en sí es una actividad de codificación adicional, pero salvo el casoexcepcional del desarrollador que codifica libre de errores, debe entenderse que estaactividad nos servirá para ahorrar tiempo en el futuro al disminuir la posibilidad de ocurrenciade errores.Por ello, se considera más apropiado hablar de limitaciones de las pruebas unitarias másque de desventajas.

Nota: Durante el año 2011 se dedicaron 1160 horas a la resolución de errores durante eldesarrollo y en período de garantía, y en 2012 se registraron 710 horas.1

LimitacionesEs importante darse cuenta de que las pruebas unitarias no descubrirán todos los erroresdel código. Por definición, sólo prueban las unidades por sí solas. Por lo tanto, nodescubrirán errores de integración, problemas de rendimiento y otros problemas que afectana todo el sistema en su conjunto. Además, puede no ser trivial anticipar todos los casosespeciales de entradas que puede recibir en realidad la unidad de programa bajo estudio.Se debe tener en consideración la ejecución diaria de las pruebas unitarias y la rápidaatención de los errores que pudieran detectarse. Si este proceso no es incorporado duranteel desarrollo puede derivar en que la aplicación quede fuera de sincronismo con los casosde prueba.Otro desafío es el desarrollo de casos de prueba realistas y útiles. Es necesario crearcondiciones iniciales para que la porción de aplicación que está siendo probada funcionecomo parte completa del sistema al que pertenece.Por último, escribir código para un caso de pruebas unitario tiene tantas probabilidades deestar libre de bugs como el mismo código que está probando.

1 Datos tomados del Sistema de Estadísticas de la Bitácora.

5 de 22

Page 6: Workshop - Pruebas Unitarias (con Java)

Pruebas Mock (Definición general)

mockHacer mímica, imitar o falsificar

Las pruebas Mock son pruebas unitarias con objetos que sustituyen a los objetos reales quela clase a probar utiliza.

Por ejemplo, si se tiene una clase Calculator, que necesita de un DAO para obtenerinformación de la base de datos, este DAO es lo que llamamos el “objeto real”. Siquisiéramos realizar una prueba de la clase Calculator, deberíamos pasarle al objeto unaconexión válida a la base de datos y asegurarnos de que los datos que necesita existan.

Este proceso de determinar los datos que el objeto necesita e insertarlos en la base requierede mucho trabajo.

En lugar de esto, se le puede proveer al objeto de una instancia falsa del DAO que sólodevuelva lo que necesitamos para la prueba.Esta clase no va a tomar la información de labase de datos, sino que va a ser un Mock.

Reemplazar el objeto real hace que probar la clase Calculator sea mucho más simple.Estrictamente hablando, dicho objeto que reemplaza al DAO real no sería un Mock, sino unStub. Luego hablaremos de esta diferencia.

Este ejemplo puntual de la clase Calculator se puede generalizar diciendo que es una unidad(Calculator) utilizando un colaborador (DAO)

Unidad → Colaborador

La flecha significa ‘usa’.

Cuando reemplazamos al colaborador por un mock (o stub), esto se puede expresar de la siguiente manera:

Unidad → Mock

En el contexto de una prueba unitaria se vería de la siguiente manera:

Prueba Unitaria → Unidad → Colaborador

o

6 de 22

Page 7: Workshop - Pruebas Unitarias (con Java)

Prueba Unitaria → Unidad → Mock

Concepto de stub, mock y proxy

Hay tres tipo de objetos falsos que se pueden usar para reemplazar a los objetosColaborador para realizar pruebas unitarias: Stub, Mock y Proxy.

Un ‘Stub’ es un objeto que implementa una interface de un componente, pero en lugar deretornar lo que el componente devolvería, el ‘stub’ puede ser configurado para retornar unvalor que se ajuste a lo que la prueba unitaria intenta probar.Utilizando ‘stubs’ se puede probar si una unidad es capaz de manejar diferentes valoresdevueltos por el colaborador.

Esto se puede expresar de la siguiente manera:

1. Prueba Unitaria → Stub2. Prueba Unitaria → Unidad → Stub

3. La prueba unitaria verifica (assert) sobre el resultado y el estado de launidad

El primer paso de la prueba unitaria es crear el objeto ‘stub’ y configurar los valores deretorno (1). Luego se crea la unidad y se le setea el ‘stub’ en lugar del colaborador “real” (2).Por último se verifica el resultado de la llamada a la unidad (3).

Un ‘Mock’ es como un ‘stub’, que además permite determinar qué métodos fueron llamadosdurante la prueba. Utilizando un ‘mock’ se puede probar tanto si los valores devueltos por launidad son los correctos, como así también si la Unidad está utilizando de forma correcta alColaborador.

Por ejemplo, no se puede ver a partir del valor devuelto desde el objeto DAO si lainformación que fue leída desde la base de datos se realizó a través de un Statement o deun PreparedStatement. Tampoco se puede determinar si el método .close() fue invocadoantes de devolver el valor. Esto es posible con ‘mocks’. Los ‘mocks’ hacen posible probar laintegración completa de la Unidad con el Colaborador.

1. Prueba Unitaria → Mock2. Prueba Unitaria → Unidad → Mock

3. La prueba unitaria verifica (assert) el resultado y el estado de la unidad.4. La prueba unitaria verifica (assert) las llamadas a los métodos en el mock.

7 de 22

Page 8: Workshop - Pruebas Unitarias (con Java)

El primer paso de la prueba unitaria es crear el objeto mock y configurar los valores deretorno (1). Luego la prueba unitaria llama a la Unidad que llama al Mock (2). Por último severifica el resultado de la llamada a la unidad (3). La prueba unitaria también realizaverificaciones con respecto a los métodos que fueron llamados en el ‘mock’ (4).

Los ‘Proxies’ son objetos ‘mock’ que delegan las llamadas a los métodos en el objetoColaborador real, pero continúa registrando internamente qué métodos fueron llamados en elproxy. Los ‘proxies’ permiten hacer pruebas mock con los colaboradores reales:

1. Prueba Unitaria → Colaborador2. Prueba Unitaria → Proxy

3. Prueba Unitaria → Unidad → Proxy → Colaborador.4. La prueba unitaria verifica (assert) el resultado y el estado de la unidad.5. La prueba unitaria verifica (assert) las llamadas a los métodos en el proxy.

El primer paso de la prueba unitaria es crear el objeto Colaborador (1). Luego la pruebaunitaria crea el Proxy para el colaborador (2). La prueba unitaria crea la unidad y le setea elproxy. Ahora la prueba unitaria llama a la unidad que llama al proxy, que a su vez llama alColaborador (3). Finalmente la prueba unitaria hace las verificaciones (assert) sobre losresultados de los métodos que llama la unidad (4). La prueba unitaria también haceverificaciones sobre los métodos invocados en el proxy. (5).

Ejemplo Stub (pseudocódigo)

public void testStub() Calculadora calculadora = new Calculadora();GenericDAO stubGenericDao = stub(GenericDAO.class);

when call (stubGenericDao.getPrimerValor()) then return(4);when call (stubGenericDao.getSegundoValor()) then return(8);calculadora.setDao(stubGenericDao);

assertEquals(new Integer(12), calculadora.sumar());

Ejemplo Mock (pseudocódigo)

public void testMock() Calculadora calculadora = new Calculadora(); GenericDAO mockGenericDao= mock(GenericDAO.class);

When call (mockGenericDao.getPrimerValor()) then return(10); When call (mockGenericDao.getSegundoValor()) then return(11);

calculadora.setDao(mockGenericDao);

8 de 22

Page 9: Workshop - Pruebas Unitarias (con Java)

assertEquals(new Integer(21), calculadora.sumar());

verify at least one call of mockGenericDao.getPrimerValor();

9 de 22

Page 10: Workshop - Pruebas Unitarias (con Java)

EstrategiasA continuación se presentan una serie de recomendaciones de acuerdo al tipo de clasesobre la que se desea desarrollar casos de prueba unitarios.

Clases de IOEn esta categoría incluimos clases o unidades que realizan operaciones de lectura oescritura de archivos.

Si la unidad realiza el procesamiento del archivo internamente, utilizar un Mock con valoresprecargados y validar el retorno.

1. Prueba Unitaria → Mock2. Prueba Unitaria → Unidad → Mock3. La prueba unitaria verifica (assert) sobre el resultado y el estado de la

unidad

Si la unidad realiza el procesamiento del archivo y delega el resultado en un colaborador,utilizar un Stub para almacenar el resultado y validarlo.

1. Prueba Unitaria → Stub2. Prueba Unitaria → Unidad → Stub3. La prueba unitaria verifica (assert) sobre el resultado y el estado de la Stub

Ejemplos

public class MyIOUnit

protected List<String> tokens = new ArrayList<String>();

public void read(InputStream input) throws IOException StringBuilder builder = new StringBuilder();

int data = input.read(); while(data != ­1) if(((char)data) != ',') builder.append((char) data); else this.tokens.add(builder.toString().trim()); builder.delete(0, builder.length());

data = input.read();

10 de 22

Page 11: Workshop - Pruebas Unitarias (con Java)

public void write(OutputStream output) throws IOException for(int i=0; i<tokens.size(); i++) if(i>0) output.write(','); output.write(tokens.get(i).getBytes());

public class MyIOUnitTest

@Test public void testRead() throws IOException MyIOUnit unit = new MyIOUnit();

byte[] data = "123,456,789,123,456,789".getBytes();

InputStream input = new ByteArrayInputStream(data);

unit.read(input);

assertEquals("123", unit.tokens.get(0)); assertEquals("456", unit.tokens.get(1)); assertEquals("789", unit.tokens.get(2)); assertEquals("123", unit.tokens.get(3)); assertEquals("456", unit.tokens.get(4)); assertEquals("789", unit.tokens.get(5));

@Test public void testWrite() throws IOException MyIOUnit unit = new MyIOUnit();

ByteArrayOutputStream output = new ByteArrayOutputStream();

unit.tokens.add("one"); unit.tokens.add("two"); unit.tokens.add("three");

unit.write(output);

String string = new String(output.toByteArray()); assertEquals("one,two,three", string);

Clases de acceso a base de datos

11 de 22

Page 12: Workshop - Pruebas Unitarias (con Java)

El objetivo al desarrollar pruebas unitarias para las clases que realizan el acceso a la basede datos será verificar que tanto las operaciones de lectura como de escritura sobre la basede datos se ejecuten correctamente, intentando mantener la consistencia de los datosalmacenados y sin necesidad de implementar lógica compleja para poder operar con losjuegos de valores o realizar una limpieza al finalizar las pruebas.

Una forma de lograr esto es ejecutando los casos de prueba dentro de una transacción y,cuando la prueba termina, realizar un rollback de esa transacción. Todas las modificacionesrealizadas serán descartadas.

Para casos de objetos que realizan las operaciones CRUD (Create Read Update Delete)puede ser más útil desarrollar un único caso de pruebas que lleve a cabo estas operacionesen forma ordenada, insertando un registro, consultando dicho registro, actualizandolo yfinalmente eliminandolo, dentro de un único test. De este modo, se evita tener que insertardatos en la base para probar la actualización o el borrado.

EjemploA continuación se da un ejemplo de prueba unitaria con Spring e Hibernate.Supondremos que la inyección de dependencias la realizará el contenedor.

Será necesario configurar la conexión a la base de datos de modo que no se realice el“commit” en forma automática:

<bean id="sessionFactory"class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">

<property name="dataSource" ref="dataSource"/><property name="configLocation"

value="classpath:hibernate.cfg.xml"/><property name="hibernateProperties">

<value>...hibernate.connection.autocommit=false...

</value></property>

</bean>

<bean id="hibernateDAO"class="com.microgestion.workshop.dao.HibernateDAO"><property name="sessionFactory" ref="sessionFactory"/>

</bean>

Luego, la prueba unitaria sería algo parecido a:

package com.microgestion.workshop.tests;

@RunWith(SpringJUnit4ClassRunner.class)

12 de 22

Page 13: Workshop - Pruebas Unitarias (con Java)

@ContextConfiguration(locations = “/META­INF/applicationContext­test.xml”)public class HibernateDAOTest

@Autowiredprivate ApplicationContext appContext;

@Testpublic void testIt() throws Exception

Session session =appContext.getBean(“sessionFactory”).getSession();

HibernateDAO dao = appContext.getBean(“hibernateDAO”);

try // Begin transactionsession.getTransaction().begin();

SomeObject obj = new SomeObject();obj.setX(“xx”); //Set properties...

// Test save()obj = dao.save(obj);assertNotNull(obj.getId());...

// Test get()obj = dao.get(obj.getId());assertEquals("xx", obj.getX());...

// Test update()obj.setX(“yy”);dao.update(obj);obj = dao.get(obj.getId());assertEquals("yy", obj.getX());

// Test delete()dao.delete(obj.getId());assertNull(dao.get(obj.getId()));

finally // Transaction roolbacksession.getTransaction().rollback();

Clases dependientes de un “Servlet Container”En este caso, para evitar tener que emular el Servlet Container y la dependencia de objetospropios del contexto de ejecución, se recomienda mover el código que implementa la lógicade negocio a una nueva clase que no tenga dependencias de la Servlet API.

13 de 22

Page 14: Workshop - Pruebas Unitarias (con Java)

Pruebas en “Dependency Injection Container”Cuando se trabaja con un contenedor de dependencias en la aplicación, se puede delegaren él la inyección de objetos mock a las unidades durante las pruebas.

Para ello, bastará con agregar anotaciones como la siguiente en la clase de prueba.

@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations = “/META­INF/applicationContext­test.xml”)

Luego, se podrá acceder al ApplicationContext agregando la propiedad y utilizando laanotación “Autowired” como se muestra en el ejemplo:

@Autowiredprivate ApplicationContext appContext;

Spring FormActionExistirá situaciones en las que resultará práctico contar con un mecanismo para hacerpruebas unitarias sobre los Action intentando evitar la necesidad del refactoring para extraerla lógica de la aplicación de clases con dependencias del contexto de ejecución.

Para ello, Spring deja disponible una serie de clases para crear objetos mock y emular dichocontexto.

Ejemplo

MockHttpServletRequest request = new MockHttpServletRequest();MockHttpServletResponse response = new MockHttpServletResponse();

// Adición de propiedades al ‘request’...

// Creación del contexto ‘mock’MockRequestContext context = new MockRequestContext();context.setExternalContext(new ServletExternalContext(null, request,response));

// Creación de la instancia del FormActionSomeFormAction action = new SomeFormAction();

// Es posible asignar el validador al FormActionSomeObjectValidator validator = new SomeObjectValidator();

14 de 22

Page 15: Workshop - Pruebas Unitarias (con Java)

action.setValidator(validator);

// La verificación dependerá del valor retornado por el FormAction// ‘Event’ en caso de invocar al método ‘bind’ o ‘bindAndValidate’Event event = action.bind(context);

// En caso de invocar un método personalizado variará el mecanismo deverificaciónOtherObject other = action.customMethod(context);

Nota: Se pueden presentar situaciones en las que es deseado acceder al ‘FlowScope’.Tener presente que este objeto también puede ser “mockeado”.

Spring ValidatorEl caso de los Validators es más simple que el anterior, dado que estas clases no presentan(en general) dependencias del contexto u otro objeto.

Es por ello, que en este caso bastará con utilizar un objeto mock con valorespreestablecidos y verificar que los errores retornados coincidan con lo esperado.

Ejemplo

SomeValidator validator = new SomeValidator();

// Creación y asignación de valores a las propiedades del objeto mockSomeObject mock = new SomeObject();

Assert.assertTrue(validator.supports(SomeObject.class));

Errors errors = validator.validate(mock);

// Verificación del resultado sobre el objeto ‘Errors’Assert.assertEquals(X, errors.getErrorCount());Assert.assertEquals(1, errors.getFieldErrorCount("somePropWithError"));...

Es importante que la prueba unitaria se realice utilizando valores del objeto considerados“válidos” tanto como valores considerados “no válidos”.

Spring Web Flow flowsEl capítulo 14 del manual de referencia de Web Flow explica detalladamente cómo construirlos casos de prueba unitarios para los flujos de una aplicación.

15 de 22

Page 17: Workshop - Pruebas Unitarias (con Java)

Java ­ Introducción a los frameworks

JUnitJUnit en su versión 4.x es un framework de pruebas que utiliza ‘annotations’ para identificarlos métodos que ejecutan pruebas. Generalmente estos métodos son llamados en clasesque son utilizadas especificamente para realizar pruebas del tipo Test.

Desde Ecipse una clase de prueba de JUnit puede ser creada de la siguiente forma:

File → New → JUnit → JUnit Test case.

Ejemplo

@Testpublic void testMultiply()

// MyClass is tested MyClass tester = new MyClass();

// Check if multiply(10,5) returns 50 assertEquals("10 x 5 must be 50", 50, tester.multiply(10, 5));

JUnit asume que los tests se pueden ejecutar en un orden arbitrario, por lo tanto un casode prueba no debe depender del resultado de otro caso.

Para correr la prueba desde Eclipse se debe hacer botón derecho en la clase a probar yluego: Run → Run As →JUnit Test.

AnnotationsLa siguiente tabla muestra una visión general de los annotations disponibles en JUnit 4.x.

Annotation Description

@Test Identifies that a method is a test method.

@Before Executes the method before each test.

@After Executes the method after each test.

@BeforeClass Executes the method once, before the start of all tests.

17 de 22

Page 18: Workshop - Pruebas Unitarias (con Java)

@AfterClass Executes the method once, after all tests have have beenfinished.

@Ignore Ignores the test method.

@Testexpected

Fails, if the method does not throw the named exception.

@Test timeout Fails, if the method takes longer than 100 milliseconds.

Assert statementsJUnit provee una serie de métodos estáticos en la clase Assert para realizar la verificaciónde diferentes condiciones. Estos métodos por lo general comienzan con la palabra ‘asserts’y permite especificar el mensaje de error, el resultado esperado y el resultado real.

La siguiente tabla muestra una visión general de estos métodos. Los parámetros entrecorchetes [] son opcionales.

Statement Description

fail(String) Let the method fail. Might be used to check that acertain part of the code is not reached. Or to have afailing test before the test code is implemented.

assertTrue([message], booleancondition)

Checks that the boolean condition is true.

assertsEquals([String message],expected, actual)

Tests that two values are the same. Note: for arraysthe reference is checked not the content of thearrays.

assertsEquals([String message],expected, actual, tolerance)

Test that float or double values match. The toleranceis the number of decimals which must be the same.

assertNull([message], object) Checks that the object is null.

assertNotNull([message], object) Checks that the object is not null.

assertSame([String], expected,actual)

0.Checks that both variables refer to the same object.

assertNotSame([String], expected,actual)

Checks that both variables refer to different objects.

18 de 22

Page 19: Workshop - Pruebas Unitarias (con Java)

Crear una suite de pruebas con JUnitSi se tienen varios casos de pruebas se los puede combinar todos en una suite. Se utiliza lasentencia @Suite.SuiteClasses

El siguiente código de ejemplo muestra una suite de prueba que define que dos clases depruebas deben ejecutarse

Ejemplo

import org.junit.runner.RunWith;import org.junit.runners.Suite;import org.junit.runners.Suite.SuiteClasses;

@RunWith(Suite.class)@SuiteClasses( MyClassTest.class, MySecondClassTest.class )public class AllTests

Mockito

Mockito es un Framework para pruebas de aplicaciones JAVA. Permite simularcomportamientos complejos de objetos, además facilita el desarrollo de test unitarios y ladetección de errores.Mockito es OpenSource y es disponible en esta dirección: http://mockito.org/Mockito se basa en el principio de un objeto mock que simula el comportamiento de otroobjeto.

La implementación de tests Mockito se hace en varias etapas: Creación del objeto mock. Descripción del comportamiento esperado Uso de los mocks Verificación que la interacción con los mocks sea correcta.

Ejemplo

@Testpublic void iterator_will_return_hello_world()

//arrangeIterator i=mock(Iterator.class);when(i.next()).thenReturn("Hello").thenReturn("World");//actString result=i.next()+" "+i.next();//assert

19 de 22

Page 20: Workshop - Pruebas Unitarias (con Java)

assertEquals("Hello World", result);

20 de 22

Page 21: Workshop - Pruebas Unitarias (con Java)

PrácticaDesarrollar los casos de prueba para la aplicación WSUnitTesting.

Paso 1: Importar la aplicación al workspace desde “\\srvprd1\Shared\Cursos\PruebasUnitarias”Paso 2: Si no se cuenta con el plugin de Maven para Eclipse, copiar las librerías de lacarpeta “\\srvprd1\Shared\Cursos\Pruebas Unitarias\libs” al proyecto.

Evaluación1. ¿Cuál es el alcance de una prueba unitaria?2. ¿Cuáles son las características que debe poseer una buena prueba unitaria?3. Defina en forma concisa en qué consiste TDD. Ejemplifique.4. ¿Cuál es la diferencia entre mock y stub?5. Supongamos que se necesita realizar pruebas de una clase DAO utilizando la base

de datos real del sistema y adicionalmente se desea verificar que un método de esaclase haya sido llamado exactamente dos veces. ¿Qué tipo de prueba realizaría?

6. Explique una forma simple de comprobar el funcionamiento de las operacionesCRUD de una DAO.

7. Explique cómo llevaría a cabo el desarrollo de una prueba unitaria sobre una claseque procesa los parámetros pasados al invocar un método y almacena el resultadoen una variable privada, accesible mediante un getter.

8. Explique cómo llevaría a cabo el desarrollo de una prueba unitaria sobre una claseque procesa los parámetros pasados como argumento sin retornar valor alguno ydelegando el resultado a un colaborador para su procesamiento posterior.

21 de 22

Page 22: Workshop - Pruebas Unitarias (con Java)

Referencias / Links útiles> Qué es un unit testhttp://msdn.microsoft.com/es­es/library/jj130731.aspx

> Stub, Mock and Proxy Testinghttp://tutorials.jenkov.com/java­unit­testing/stub­mock­and­proxy­testing.html

> Mocks Aren't Stubshttp://www.martinfowler.com/articles/mocksArentStubs.html

> Wikipedia ­ Prueba unitariahttp://es.wikipedia.org/wiki/Prueba_unitaria

> JUnit testing Hibernate and Springhttp://www.disasterarea.co.uk/blog/?p=75

> JUnit Tutorialhttp://www.vogella.com/articles/JUnit/article.htm

> Mockito in six easy exampleshttp://gojko.net/2009/10/23/mockito­in­six­easy­examples/

> disableAutoCommit in Hibernatehttp://www.coderanch.com/t/463713/ORM/databases/disabling­autoCommit­hibernate

22 de 22