Diferencia entre revisiones de «Captura De Parametros»

De Dos Ideas.
Saltar a: navegación, buscar
(El problema)
(Una posible solución)
Línea 72: Línea 72:
 
===Una posible solución===
 
===Una posible solución===
  
Tenemos así la clase PlanInvasionBoImpl que la implementa. Esta clase se comunica con un [[DAO]] para realizar la búsqueda del objeto de dominio Invasor. Luego de obtenerlo, lo convierte a un InvasorDto y lo devuelve.
+
Una posible solución a nuestro objetivo es capturar el parámetro Filtro que recibe el método del DAO que en el caso del test será un [[Mock Object]].
  
 
=Captura de parámetro con EasyMock=
 
=Captura de parámetro con EasyMock=

Revisión del 17:52 10 oct 2008

Hay situaciones en las que el estamos realizando un testeo con un Mock Object y queremos capturar un parámetro que recibe el mismo.

Esta situación suele producirse cuando hay un objeto que se crea dentro de los objetos que estamos probando y llega como parámetro a algún Mock Object. Hay unas cuantas condiciones que podemos pedir a EasyMock y Mockito que validen como parámetro esperado como por ejemplo igualdad, expresiones regulares, no nulo, nulo, algunas comprobaciones con Strings y primitivos, etc. Pero incluso a veces esto no alcanza. El objeto fue creado dentro de otro objeto, es decir que no podemos ni inyectarlo desde fuera ni conseguirlo por medios naturales y queremos inspeccionar sus atributos y realizar una serie de asserts. Es ahí cuando conseguir una referencia al mismo nos resulta indispensable.

Ejemplo

El escenario

Supongamos la siguiente interfaz de negocio:

public interface PlanInvasionBo {
    public InvasorDto findInvasorMasPeligroso();
}

... la siguiente interfaz de DAO

public interface PlanInvasionDao {
    public Invasor findInvasorPorFiltro(Filtro filtro);
}

... y el siguiente filtro

public class Filtro {
    private Fuerza fuerza;
    private Velocidad velocidad;
    private Destreza destreza;
    // sus metodos accesores
}

Dentro de la implementación de la clase PlanInvasionBo se crea una instancia de Filtro que se utiliza para comunicarse con el DAO pero no es externalizada en ningún momento (salvo como parámetro en la llamada al método del DAO) ni existe la posiblidad de inyectarla desde fuera.

public class PlanInvasorBoImpl implements PlanInvasor {
    private PlanInvasionDao planInvasionDao;
    // otros atributos
    
    public Invasor findInvasorMasPeligroso() {
        // Realiza ciertos guarismos internos 
        // para determinar la Fuerza, Velocidad y Destreza
        Fuerza fuerza = calcularFuerza();
        Velocidad velocidad = calcularVelocidad();
        Destreza destreza = calcularDestreza();
        // Utiliza los valores determinados para construir un Filtro
        Filtro filtro = new Filtro(fuerza, velocidad, destreza);
        // Llama al DAO con el filtro construido internamente
        return planInvasionDao.findInvasorPorFiltro(filtro);
    }
    // otros metodos
}

El objetivo

El objetivo que nos planteamos es poder inspeccionar en un test que los valores del objeto Velocidad estén dentro de ciertos límites.

El problema

El problema que tenemos es que el objeto Velocidad se crea a partir de unos métodos privados de PlanInvasionBo y está dentro de otro objeto que se crea también dentro de PlanInvasionBo al que tampoco tenemos acceso. La única comunicación de este objeto con el exterior es en forma de parámetro a través de la llamada al método del DAO.

Una posible solución

Una posible solución a nuestro objetivo es capturar el parámetro Filtro que recibe el método del DAO que en el caso del test será un Mock Object.

Captura de parámetro con EasyMock

La forma de capturar un parámetro con EasyMock es creando un objeto Capture parametrizado con la clase que va a capturar. Luego, en la maquetación del método, se utiliza el método estático EasyMock.capture que recibe al capturador. Luego de ejercitar el método podemos pedirle el valor capturado al capturador.

package test.com.dosideas.mock.business.impl;
//imports varios...
import static org.easymock.EasyMock.*;
public class PlanInvasionBoImplTest extends TestCase {
    private PlanInvasionBoImpl planInvasionBo;
    private PlanInvasionDao daoMock;
    protected void setUp() throws Exception {
        daoMock = createMock(PlanInvasionDao.class);
        planInvasionBo = new PlanInvasionBoImpl();
        planInvasionBo.setPlanInvasionDao(daoMock);
    }
    public void testFindInvasorMasPeligroso() {
        Invasor invasor = new Invasor(id, "Zim");
        // Crear un Capture para utilizar en la maquetacion del metodo
        Capture<Filtro> caturaFiltro = new Capture<Filtro>();
        expect(mockDao.findInvasorPorFilro(capture(capturaFiltro)).andReturn(invasor);
        replay(mockDao);
        InvasorDto resultado = planInvasionBo.findInvasorById(id);
        verify(mockDao);
        // los assert tipicos
        
        // Conseguir la referencia al filtro que llego como parametro
        // al metodo del daoMock
        Filtro filtro = capturaFiltro.getValue();
        assertNotNull(filtro);
        assertTrue(filtro.getVelocidad() < VELOCIDAD_MAXIMA);
        // El resto de los asserts necesarios sobre el filtro
    }
}

Captura de parámetro con Mockito

(Agregar descripcion y codigo de Mockito)

Extensión del Matcher de Mockito

(Agregar descripcion y codigo del Matcher capturador)

Ver también