Workshop
Tema: Pruebas unitarias
Autores
●
●

Luciano Martinez
Andrés Sommariva

Fecha
●

Marzo 2013

Versión: 1.0

1 de 22
Índice
Teoría
¿Por qué pruebas unitarias?
Introducción
Características
Ventajas
Desventajas
Limitaciones
Pruebas Mock (Definición general)
mock
Concepto de stub, mock y proxy
Ejemplo Stub (pseudocódigo)
Ejemplo Mock (pseudocódigo)
Estrategias
Clases de IO
Ejemplos
Clases de acceso a base de datos
Ejemplo
Clases dependientes de un “Servlet Container”
Pruebas en “Dependency Injection Container”
Spring FormAction
Ejemplo
Spring Validator
Ejemplo
Spring Web Flow flows
Java ­ Introducción a los frameworks
JUnit
Ejemplo
Assert statements
Crear una suite de pruebas con JUnit
Práctica
Evaluación
Referencias / Links útiles

2 de 22
Pruebas unitarias
Teorí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 convierte
en un círculo vicioso. Cuanta más presión se siente, menos pruebas se realizan. Cuantas
menos 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ón
Un unit test es un método que prueba una unidad de código. Al hablar de una unidad de
código nos referimos a un requerimiento. Muchos desarrolladores tienen su propio concepto
de lo que es una prueba unitaria; sin embargo, la gran mayoría coincide en que una prueba
unitaria tiene las siguientes características:
● Prueba solamente pequeñas cantidades de código: Solamente prueba el código del
requerimiento específico.
● Se aísla de otro código y de otros desarrolladores: El unit test prueba exclusivamente
el código relacionado con el requerimiento y no interfiere con el trabajo hecho por
otros desarrolladores.
● Solamente se prueban los endpoints públicos: Esto principalmente porque los
disparadores de los métodos privados son métodos públicos por lo tanto se abarca
el código de los métodos privados dentro de las pruebas.
● Los resultados son automatizados: Cuando ejecutamos las pruebas lo podemos
hacer de forma individual o de forma grupal. Estas pruebas las hace el motor de
prueba y los resultados de los mismos deben de ser precisos con respecto a cada
prueba unitaria desarrollada
● Repetible y predecible: No importa el orden y las veces que se repita la prueba, el
resultado 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 deben
de ser simples y rápidos de desarrollar. Difícilmente una prueba unitaria deba de
tomar más de cinco minutos en su desarrollo.

3 de 22
Características
Para que una prueba unitaria sea buena debe cumplir los siguientes requisitos:
● Automatizable: No debería requerirse una intervención manual. Esto es
especialmente ú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.

Ventajas
El objetivo de las pruebas unitarias es aislar cada parte del programa y mostrar que las
partes individuales son correctas. Proporcionan un contrato escrito que el trozo de código
debe satisfacer. Estas pruebas aisladas proporcionan cinco ventajas básicas:
● Fomentan el cambio
Las pruebas unitarias facilitan que el programador cambie el código para mejorar su
estructura (lo que se ha dado en llamar refactorización), puesto que permiten hacer
pruebas sobre los cambios y así asegurarse de que los nuevos cambios no han
introducido errores.
● Simplifica la integración
Puesto que permiten llegar a la fase de integración con un grado alto de seguridad de
que el código está funcionando correctamente. De esta manera se facilitan las
pruebas de integración.
● Documenta el código
Las propias pruebas son documentación del código puesto que ahí se puede ver
cómo utilizarlo.
● Separación de la interfaz y la implementación
Dado que la única interacción entre los casos de prueba y las unidades bajo prueba
son las interfaces de estas últimas, se puede cambiar cualquiera de los dos sin
afectar al otro, a veces usando objetos mock (mock object) para simular el
comportamiento de objetos complejos.
● Los errores están más acotados y son más fáciles de localizar
Dado que tenemos pruebas unitarias que pueden desenmascararlos.
● Mejoran el diseño
En prácticas como Test Driven Development (TDD) permiten plantear el
comportamiento esperado en un paso previo a la codificación.
● Puede ser la forma más simple de verificar el funcionamiento
En situaciones como el desarrollo de una API o un componente que brinda servicios
del cual no se cuenta aún con un cliente para consumirlos.

4 de 22
Desventajas
El desarrollo de los casos de prueba unitarios puede ser percibido como una pérdida de
tiempo dado que en sí es una actividad de codificación adicional, pero salvo el caso
excepcional del desarrollador que codifica libre de errores, debe entenderse que esta
actividad nos servirá para ahorrar tiempo en el futuro al disminuir la posibilidad de ocurrencia
de errores.
Por ello, se considera más apropiado hablar de limitaciones de las pruebas unitarias más
que de desventajas.
Nota: Durante el año 2011 se dedicaron 1160 horas a la resolución de errores durante el
desarrollo y en período de garantía, y en 2012 se registraron 710 horas.1

Limitaciones
Es importante darse cuenta de que las pruebas unitarias no descubrirán todos los errores
del código. Por definición, sólo prueban las unidades por sí solas. Por lo tanto, no
descubrirán errores de integración, problemas de rendimiento y otros problemas que afectan
a todo el sistema en su conjunto. Además, puede no ser trivial anticipar todos los casos
especiales 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ápida
atención de los errores que pudieran detectarse. Si este proceso no es incorporado durante
el desarrollo puede derivar en que la aplicación quede fuera de sincronismo con los casos
de prueba.
Otro desafío es el desarrollo de casos de prueba realistas y útiles. Es necesario crear
condiciones iniciales para que la porción de aplicación que está siendo probada funcione
como parte completa del sistema al que pertenece.
Por último, escribir código para un caso de pruebas unitario tiene tantas probabilidades de
estar 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
Pruebas Mock (Definición general)
mock
Hacer mímica, imitar o falsificar
Las pruebas Mock son pruebas unitarias con objetos que sustituyen a los objetos reales que
la clase a probar utiliza.
Por ejemplo, si se tiene una clase Calculator, que necesita de un DAO para obtener
información de la base de datos, este DAO es lo que llamamos el “objeto real”. Si
quisiéramos realizar una prueba de la clase Calculator, deberíamos pasarle al objeto una
conexió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 requiere
de mucho trabajo.
En lugar de esto, se le puede proveer al objeto de una instancia falsa del DAO que sólo
devuelva lo que necesitamos para la prueba.Esta clase no va a tomar la información de la
base 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 un
Stub. 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
Prueba Unitaria → Unidad → Mock

Concepto de stub, mock y proxy
Hay tres tipo de objetos falsos que se pueden usar para reemplazar a los objetos
Colaborador para realizar pruebas unitarias: Stub, Mock y Proxy.
Un ‘Stub’ es un objeto que implementa una interface de un componente, pero en lugar de
retornar lo que el componente devolvería, el ‘stub’ puede ser configurado para retornar un
valor que se ajuste a lo que la prueba unitaria intenta probar.
Utilizando ‘stubs’ se puede probar si una unidad es capaz de manejar diferentes valores
devueltos por el colaborador.
Esto se puede expresar de la siguiente manera:
1. Prueba Unitaria → Stub
2. Prueba Unitaria → Unidad → Stub
3. La prueba unitaria verifica (assert) sobre el resultado y el estado de la
unidad
El primer paso de la prueba unitaria es crear el objeto ‘stub’ y configurar los valores de
retorno (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 llamados
durante la prueba. Utilizando un ‘mock’ se puede probar tanto si los valores devueltos por la
unidad son los correctos, como así también si la Unidad está utilizando de forma correcta al
Colaborador.
Por ejemplo, no se puede ver a partir del valor devuelto desde el objeto DAO si la
información que fue leída desde la base de datos se realizó a través de un Statement o de
un PreparedStatement. Tampoco se puede determinar si el método .close() fue invocado
antes de devolver el valor. Esto es posible con ‘mocks’. Los ‘mocks’ hacen posible probar la
integración completa de la Unidad con el Colaborador.
1. Prueba Unitaria → Mock
2. 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
El primer paso de la prueba unitaria es crear el objeto mock y configurar los valores de
retorno (1). Luego la prueba unitaria llama a la Unidad que llama al Mock (2).  Por último se
verifica el resultado de la llamada a la unidad (3). La prueba unitaria también realiza
verificaciones 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 objeto
Colaborador real, pero continúa registrando internamente qué métodos fueron llamados en el
proxy. Los ‘proxies’ permiten hacer pruebas mock con los colaboradores reales:
1. Prueba Unitaria → Colaborador
2. 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 prueba
unitaria crea el Proxy para el colaborador (2). La prueba unitaria crea la unidad y le setea el
proxy. Ahora la prueba unitaria llama a la unidad que llama al proxy, que a su vez llama al
Colaborador (3). Finalmente la prueba unitaria hace las verificaciones (assert) sobre los
resultados de los métodos que llama la unidad (4). La prueba unitaria también hace
verificaciones sobre los métodos invocados en el proxy. (5).
Ejemplo Stub (pseudocódigo)
pbi odtsSu( 
ulcvi ettb){
Cluaoacluaoa=nwCluaoa)
acldr acldr  e acldr(;
GnrcA tbeeiDo=su(eeiDOcas;
eeiDOsuGnrca  tbGnrcA.ls)
we al(tbeeiDogtrmrao()te eun4;
hncl suGnrca.ePieVlr) hnrtr()
we al(tbeeiDogteudVlr) hnrtr()
hncl suGnrca.eSgnoao()te eun8;
cluaoasta(tbeeiDo;
acldr.eDosuGnrca)
asrEul(e nee(2,cluaoasmr);
setqasnwItgr1) acldr.ua()
}

Ejemplo Mock (pseudocódigo)
pbi odtsMc( 
ulcvi etok){
 Cluaoacluaoa=nwCluaoa)
 acldr acldr  e acldr(;
 GnrcA okeeiDo okGnrcA.ls)
 eeiDOmcGnrca=mc(eeiDOcas;
 We al(okeeiDogtrmrao()te eun1)
 hncl mcGnrca.ePieVlr) hnrtr(0;
 We al(okeeiDogteudVlr) hnrtr(1;
 hncl mcGnrca.eSgnoao()te eun1)
 cluaoasta(okeeiDo;
 acldr.eDomcGnrca)

8 de 22
 asrEul(e nee(1,cluaoasmr);
 setqasnwItgr2) acldr.ua()
 vrf tlatoecl fmcGnrca.ePieVlr)
 eiya es n alo okeeiDogtrmrao(;
}

9 de 22
Estrategias
A continuación se presentan una serie de recomendaciones de acuerdo al tipo de clase
sobre la que se desea desarrollar casos de prueba unitarios.

Clases de IO
En esta categoría incluimos clases o unidades que realizan operaciones de lectura o
escritura de archivos.
Si la unidad realiza el procesamiento del archivo internamente, utilizar un Mock con valores
precargados y validar el retorno.
1. Prueba Unitaria → Mock
2. Prueba Unitaria → Unidad → Mock
3. 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 → Stub
2. Prueba Unitaria → Unidad → Stub
3. La prueba unitaria verifica (assert) sobre el resultado y el estado de la Stub

Ejemplos
pbi ls yOnt{
ulccasMIUi 
  poetdLs<tig oes=nwAryitSrn>)
  rtce itSrn>tkn  e raLs<tig(;
  pbi odra(nuSra nu)trw Oxeto 
  ulcvi edIpttemipt hosIEcpin{
    SrnBidrbidr=nwSrnBidr)
    tigule ule  e tigule(;
    itdt  nu.ed)
    n aa=iptra(;
    wiedt =­)
    hl(aa! 1{
      i((hrdt)! ,)
      f(ca)aa =''{
        bidrapn(ca)dt)
        ule.ped(hr aa;
      }es 
       le{
        ti.oesadbidrtSrn(.rm);
        hstkn.d(ule.otig)ti()
        bidrdlt(,bidrlnt()
        ule.eee0 ule.egh);
      }
      
      dt  nu.ed)
      aa=iptra(;
    }
    
  }
  

10 de 22
  pbi odwieOtuSra upt hosIEcpin{
  ulcvi rt(upttemotu)trw Oxeto 
    friti0 <oessz(;i+{
    o(n =;itkn.ie) +)
      i(>)
      fi0{
        otu.rt(,)
        uptwie'';
      }
      
      otu.rt(oesgti.eBts);
      uptwietkn.e()gtye()
    
   }
  }
  
}

pbi ls yOntet{
ulccasMIUiTs 
  @et
  Ts
  pbi odtsRa( hosIEcpin{
  ulcvi eted)trw Oxeto 
    MIUi nt=nwMIUi(;
    yOntui  e yOnt)
    bt[ aa="2,5,8,2,5,8"gtye(;
    ye]dt  134679134679.eBts)
    Ipttemipt=nwBtArynuSra(aa;
    nuSra nu  e yeraIpttemdt)
    ui.edipt;
    ntra(nu)
    asrEul(13,ui.oesgt0)
    setqas"2" nttkn.e();
    asrEul(46,ui.oesgt1)
    setqas"5" nttkn.e();
    asrEul(79,ui.oesgt2)
    setqas"8" nttkn.e();
    asrEul(13,ui.oesgt3)
    setqas"2" nttkn.e();
    asrEul(46,ui.oesgt4)
    setqas"5" nttkn.e();
    asrEul(79,ui.oesgt5)
    setqas"8" nttkn.e();
  }
  
  @et
  Ts
  pbi odtsWie)trw Oxeto 
  ulcvi etrt( hosIEcpin{
    MIUi nt=nwMIUi(;
    yOntui  e yOnt)
    BtAryupttemotu  e yeraOtuSra(;
    yeraOtuSra upt=nwBtAryupttem)
    ui.oesad"n";
    nttkn.d(oe)
    ui.oesad"w";
    nttkn.d(to)
    ui.oesad"he";
    nttkn.d(tre)
    ui.rt(upt;
    ntwieotu)
    Srn tig=nwSrn(upttBtAry);
    tigsrn  e tigotu.oyera()
    asrEul(oetotre,srn)
    setqas"n,w,he" tig;
  }
  
}

Clases de acceso a base de datos
11 de 22
El objetivo al desarrollar pruebas unitarias para las clases que realizan el acceso a la base
de datos será verificar que tanto las operaciones de lectura como de escritura sobre la base
de datos se ejecuten correctamente, intentando mantener la consistencia de los datos
almacenados y sin necesidad de implementar lógica compleja para poder operar con los
juegos 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 modificaciones
realizadas 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 operaciones
en forma ordenada, insertando un registro, consultando dicho registro, actualizandolo y
finalmente eliminandolo, dentro de un único test. De este modo, se evita tener que insertar
datos en la base para probar la actualización o el borrado.
Ejemplo
A 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:
<eni=ssinatr"
ba d"esoFcoy
cas"r.pigrmwr.r.ient3antto.noainesoFc
ls=ogsrnfaeokomhbrae.noainAnttoSsina
trBa"
oyen>
<rprynm=dtSuc"rf"aaore/
poet ae"aaore e=dtSuc">
<rprynm=cniLcto"
poet ae"ofgoain
vle"lspt:ient.f.m">
au=casahhbraecgxl/
<rprynm=hbraerpris>
poet ae"ientPoete"
<au>
vle
..
.
hbraecneto.uoomtfle
ient.oncinatcmi=as
..
.
<vle
/au>
<poet>
/rpry
<ba>
/en
<eni=hbraeA"
ba d"ientDO
cas"o.irgsinwrso.a.ientDO>
ls=cmmcoeto.okhpdoHbraeA"
<rprynm=ssinatr"rf"esoFcoy/
poet ae"esoFcoy e=ssinatr">
<ba>
/en

Luego, la prueba unitaria sería algo parecido a:
pcaecmmcoeto.okhptss
akg o.irgsinwrso.et;
@uWt(pigUi4lsRne.ls)
RnihSrnJntCasunrcas

12 de 22
@otxCniuainlctos={/EAIFapiainotx­etxl
Cnetofgrto(oain  “MT­N/plctoCnetts.m
”)
}
pbi ls ientDOet{
ulccasHbraeATs 
@uoie
Atwrd
piaeApiainotx pCnet
rvt plctoCnetapotx;
@et
Ts
pbi odtsI( hosEcpin{
ulcvi ett)trw xeto 
Ssinssin=
eso eso 
apotx.eBa(ssinatr”.eSsin)
pCnetgten“esoFcoy)gteso(;
HbraeA a  pCnetgten“ientDO)
ientDOdo=apotx.eBa(hbraeA”;
ty{
r 
/ ei rnato
/Bgntascin
ssingtrnato(.ei(;
eso.eTascin)bgn)
SmOjc b  e oebet)
oebetoj=nwSmOjc(;
ojst(x”;/Stpoete
b.eX“x) /e rpris
..
.
/ etsv(
/Ts ae)
oj=dosv(b)
b  a.aeoj;
asrNtulojgtd);
setoNl(b.eI()
..
.
/ etgt)
/Ts e(
oj=dogtojgtd);
b  a.e(b.eI()
asrEul(x" b.eX);
setqas"x,ojgt()
..
.
/ etudt(
/Ts pae)
ojst(y”;
b.eX“y)
doudt(b)
a.paeoj;
oj=dogtojgtd);
b  a.e(b.eI()
asrEul(y" b.eX);
setqas"y,ojgt()
/ etdlt(
/Ts eee)
dodlt(b.eI()
a.eeeojgtd);
asrNl(a.e(b.eI();
setuldogtojgtd))
 }fnly{
  ial 
/ rnato olak
/Tascinrobc
ssingtrnato(.olak)
eso.eTascin)rlbc(;
 }
 
}

Clases dependientes de un “Servlet Container”
En este caso, para evitar tener que emular el Servlet Container y la dependencia de objetos
propios del contexto de ejecución, se recomienda mover el código que implementa la lógica
de negocio a una nueva clase que no tenga dependencias de la Servlet API.
13 de 22
Pruebas en “Dependency Injection Container”
Cuando se trabaja con un contenedor de dependencias en la aplicación, se puede delegar
en é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.

@uWt(pigUi4lsRne.ls)
RnihSrnJntCasunrcas
@otxCniuainlctos={/EAIFapiainotx­etxl
Cnetofgrto(oain  “MT­N/plctoCnetts.m
”)
}

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

@uoie
Atwrd
piaeApiainotx pCnet
rvt plctoCnetapotx;

Spring FormAction
Existirá situaciones en las que resultará práctico contar con un mecanismo para hacer
pruebas unitarias sobre los Action intentando evitar la necesidad del refactoring para extraer
la 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 dicho
contexto.
Ejemplo

McHtSrlteus eus  e oktpeveRqet)
oktpeveRqetrqet=nwMcHtSrlteus(;
McHtSrltepnersos  e oktpeveRsos(;
oktpeveRsos epne=nwMcHtSrltepne)
/ dcó epoiddsa rqet..
/Aiind rpeae l‘eus’.
/ raindlcnet mc’
/Cecó e otxo‘ok
McRqetotx otx  e okeusCnet)
okeusCnetcnet=nwMcRqetotx(;
cnetstxenlotx(e eveEtraCnetnl,rqet
otx.eEtraCnetnwSrltxenlotx(ul eus,
rsos);
epne)
/ raind aisacadlFrAto
/Cecó el ntni e omcin
SmFrAto cin=nwSmFrAto(;
oeomcinato  e oeomcin)
/ spsbeainre aiao lFrAto
/E oil sga lvlddra omcin
SmOjcVldtrvldtr=nwSmOjcVldtr)
oebetaiao aiao  e oebetaiao(;

14 de 22
ato.eVldtrvldtr;
cinstaiao(aiao)
/ avrfccó eedr e ao eond o lFrAto
/L eiiaindpneádlvlrrtraopre omcin
/ Eet ncs eivcra éoo‘id  bnAdaiae
/‘vn’e aod noa lmtd bn’o‘idnVldt’
Eeteet=ato.idcnet;
vn vn  cinbn(otx)
/ ncs eivcru éooproaiaovraáe eaim e
/E aod noa nmtd esnlzd air lmcnsod
vrfccó
eiiain
Ohrbetohr=ato.utmehdcnet;
teOjc te  cincsoMto(otx)

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

Spring Validator
El 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 valores
preestablecidos y verificar que los errores retornados coincidan con lo esperado.
Ejemplo

SmVldtrvldtr=nwSmVldtr)
oeaiao aiao  e oeaiao(;
/ rainyaincó evlrsalspoiddsdlojt ok
/Cecó  sgaind aoe  a rpeae e beomc
SmOjc ok=nwSmOjc(;
oebetmc  e oebet)
Asr.setrevldtrspot(oebetcas)
setasrTu(aiao.uprsSmOjc.ls);
Err ros=vldtrvldt(ok;
roserr  aiao.aiaemc)
/ eiiaindlrslaosbee beo‘ros
/Vrfccó e eutd or lojt Err’
Asr.setqasX rosgtroCut);
setasrEul(,err.eErron()
Asr.setqas1 rosgtilErron(smPoWtErr);
setasrEul(,err.eFedroCut"oerpihro")
..
.

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 flows
El capítulo 14 del manual de referencia de Web Flow explica detalladamente cómo construir
los casos de prueba unitarios para los flujos de una aplicación.

15 de 22
> 14. Testing flows
http://static.springsource.org/spring­webflow/docs/2.0.x/reference/htmlsingle/spring­webflow­
reference.html#testing
Este tipo de pruebas está enfocada en la validación de las transiciones.

16 de 22
Java ­ Introducción a los frameworks
JUnit
JUnit en su versión 4.x es un framework de pruebas que utiliza ‘annotations’ para identificar
los métodos que ejecutan pruebas. Generalmente estos métodos son llamados en clases
que 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
@et
Ts
pbi odtsMlil( 
ulcvi etutpy){
  /MCasi etd
 / yls stse
  yls etr=nwMCas)
 MCastse  e yls(;
  /Ceki utpy1,)rtrs5
 / hc fmlil(05 eun 0
  setqas"0x5ms e5" 0 etrmlil(0 );
 asrEul(1   utb 0,5,tse.utpy1,5)
 
}

JUnit asume que los tests se pueden ejecutar en un orden arbitrario, por lo tanto un caso
de 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 y
luego: Run → Run As →JUnit Test.

Annotations
La siguiente tabla muestra una visión general de los annotations disponibles en JUnit 4.x.
Annotation
@Test

Description
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
@AfterClass

Executes the method once, after all tests have have been
finished.

@Ignore

Ignores the test method.

@Test
expected

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

@Test timeout

Fails, if the method takes longer than 100 milliseconds.

Assert statements
JUnit provee una serie de métodos estáticos en la clase Assert para realizar la verificación
de 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 entre
corchetes [] son opcionales.
Statement

Description

fail(String)

Let the method fail. Might be used to check that a
certain part of the code is not reached. Or to have a
failing test before the test code is implemented.

assertTrue([message], boolean
condition)

Checks that the boolean condition is true.

assertsEquals([String message],
expected, actual)

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

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

Test that float or double values match. The tolerance
is 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, Checks that both variables refer to different objects.
actual)
18 de 22
Crear una suite de pruebas con JUnit
Si se tienen varios casos de pruebas se los puede combinar todos en una suite. Se utiliza la
sentencia @Suite.SuiteClasses
El siguiente código de ejemplo muestra una suite de prueba que define que dos clases de
pruebas deben ejecutarse
Ejemplo
ipr r.ui.unrRnih
motogjntrne.uWt;
ipr r.ui.unr.ut;
motogjntrnesSie
ipr r.ui.unr.ut.utCass
motogjntrnesSieSielse;
@uWt(ut.ls)
RnihSiecas
@utCass
Sielse(
 {MCasetcas yeodlsTs.ls 
  ylsTs.ls,MScnCasetcas}
)
pbi ls lTss{
ulccasAlet 
}

Mockito
Mockito es un Framework para pruebas de aplicaciones JAVA. Permite simular
comportamientos complejos de objetos, además facilita el desarrollo de test unitarios y la
detecció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 otro
objeto.
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

@et
Ts
pbi odieao_ilrtr_el_ol({
ulcvi trtrwl_eunhlowrd)
/arne
/rag
Ieao =okIeao.ls)
trtrimc(trtrcas;
we(.et).hneun"el".hneun"ol";
hninx()teRtr(Hlo)teRtr(Wrd)
/at
/c
Srn eutinx(+ +.et)
tigrsl=.et)""inx(;
/asr
/set

19 de 22
asrEul(HloWrd,rsl)
setqas"el ol" eut;
}

20 de 22
Práctica
Desarrollar los casos de prueba para la aplicación WSUnitTesting.
Paso 1: Importar la aplicación al workspace desde “srvprd1SharedCursosPruebas
Unitarias”
Paso 2: Si no se cuenta con el plugin de Maven para Eclipse, copiar las librerías de la
carpeta “srvprd1SharedCursosPruebas Unitariaslibs” al proyecto.

Evaluación
1.
2.
3.
4.
5.

¿Cuál es el alcance de una prueba unitaria?
¿Cuáles son las características que debe poseer una buena prueba unitaria?
Defina en forma concisa en qué consiste TDD. Ejemplifique.
¿Cuál es la diferencia entre mock y stub?
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 esa
clase haya sido llamado exactamente dos veces. ¿Qué tipo de prueba realizaría?
6. Explique una forma simple de comprobar el funcionamiento de las operaciones
CRUD de una DAO.
7. Explique cómo llevaría a cabo el desarrollo de una prueba unitaria sobre una clase
que procesa los parámetros pasados al invocar un método y almacena el resultado
en una variable privada, accesible mediante un getter.
8. Explique cómo llevaría a cabo el desarrollo de una prueba unitaria sobre una clase
que procesa los parámetros pasados como argumento sin retornar valor alguno y
delegando el resultado a un colaborador para su procesamiento posterior.

21 de 22
Referencias / Links útiles
> Qué es un unit test
http://msdn.microsoft.com/es­es/library/jj130731.aspx
> Stub, Mock and Proxy Testing
http://tutorials.jenkov.com/java­unit­testing/stub­mock­and­proxy­testing.html
> Mocks Aren't Stubs
http://www.martinfowler.com/articles/mocksArentStubs.html
> Wikipedia ­ Prueba unitaria
http://es.wikipedia.org/wiki/Prueba_unitaria
> JUnit testing Hibernate and Spring
http://www.disasterarea.co.uk/blog/?p=75
> JUnit Tutorial
http://www.vogella.com/articles/JUnit/article.htm
> Mockito in six easy examples
http://gojko.net/2009/10/23/mockito­in­six­easy­examples/
> disableAutoCommit in Hibernate
http://www.coderanch.com/t/463713/ORM/databases/disabling­autoCommit­hibernate

22 de 22

Workshop - Pruebas Unitarias (con Java)