Pregunta

Una forma de pensar acerca de esto es:. Si nos preocupa el diseño del código, a continuación EasyMock es la mejor opción, ya que proporciona información a usted por su concepto de expectativas

Si nos preocupa la capacidad de mantenimiento de pruebas (más fácil de leer, escribir y tener pruebas menos quebradizas que no se ven afectados tanto por el cambio), entonces Mockito parece una mejor opción.

Mis preguntas son:

  • Si ha utilizado EasyMock en proyectos a gran escala, ¿Le parece que sus pruebas son más difíciles de mantener?
  • ¿Cuáles son las limitaciones de Mockito (salvo pruebas de endo)?
¿Fue útil?

Solución

Soy un desarrollador EasyMock así que un poco parcial, pero por supuesto que he usado EasyMock en proyectos a gran escala.

Mi opinión es que las pruebas de EasyMock de hecho se rompe una vez en un rato. EasyMock te obliga a hacer una grabación completa de lo que espera. Esto requiere cierta disciplina. Usted realmente debe registrar lo que se espera que no lo necesita actualmente el método probado. Por ejemplo, si no importa cuántas veces se llama a un método en una maqueta, no tenga miedo de usar andStubReturn. Además, si no se preocupan por un parámetro, anyObject() uso y así sucesivamente. Pensando en TDD puede ayudar en eso.

Mi analizar es que las pruebas EasyMock se romperán más a menudo, pero los Mockito no cuando quieren que lo hagan. Prefiero que mis pruebas de ruptura. Por lo menos estoy al tanto de lo que fue el impacto de mi desarrollo. Esto es, por supuesto, mi punto de vista personal.

Otros consejos

No será discutir sobre la legibilidad de prueba, tamaño o técnicas de estos marcos de prueba, creo que son iguales, pero en un ejemplo sencillo te muestro la diferencia.

Teniendo en cuenta: Tenemos una clase que se encarga de almacenar algo en alguna parte:

public class Service {

    public static final String PATH = "path";
    public static final String NAME = "name";
    public static final String CONTENT = "content";
    private FileDao dao;

    public void doSomething() {
        dao.store(PATH, NAME, IOUtils.toInputStream(CONTENT));
    }

    public void setDao(FileDao dao) {
        this.dao = dao;
    }
}

y queremos probarlo:

Mockito:

public class ServiceMockitoTest {

    private Service service;

    @Mock
    private FileDao dao;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        service = new Service();
        service.setDao(dao);
    }

    @Test
    public void testDoSomething() throws Exception {
        // given
        // when
        service.doSomething();
        // then
        ArgumentCaptor<InputStream> captor = ArgumentCaptor.forClass(InputStream.class);
        Mockito.verify(dao, times(1)).store(eq(Service.PATH), eq(Service.NAME), captor.capture());
        assertThat(Service.CONTENT, is(IOUtils.toString(captor.getValue())));
    }
}

EasyMock:

public class ServiceEasyMockTest {
    private Service service;
    private FileDao dao;

    @Before
    public void setUp() {
        dao = EasyMock.createNiceMock(FileDao.class);
        service = new Service();
        service.setDao(dao);
    }

    @Test
    public void testDoSomething() throws Exception {
        // given
        Capture<InputStream> captured = new Capture<InputStream>();
        dao.store(eq(Service.PATH), eq(Service.NAME), capture(captured));
        replay(dao);
        // when
        service.doSomething();
        // then
        assertThat(Service.CONTENT, is(IOUtils.toString(captured.getValue())));
        verify(dao);
    }
}

Como se puede ver tanto la prueba son bastante iguales y ambos están pasando. Ahora, imaginemos que alguien Implementación del servicio lo demás cambiado y tratar de ejecutar las pruebas.

aplicación nuevo servicio:

dao.store(PATH + separator, NAME, IOUtils.toInputStream(CONTENT));

se añadió separador al final de constante PATH

Como resultados de las pruebas se verá como en este momento? En primer lugar las dos pruebas fallarán, pero con diferentes mensajes de error:

EasyMock:

java.lang.AssertionError: Nothing captured yet
    at org.easymock.Capture.getValue(Capture.java:78)
    at ServiceEasyMockTest.testDoSomething(ServiceEasyMockTest.java:36)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)

Mockito:

Argument(s) are different! Wanted:
dao.store(
    "path",
    "name",
    <Capturing argument>
);
-> at ServiceMockitoTest.testDoSomething(ServiceMockitoTest.java:34)
Actual invocation has different arguments:
dao.store(
    "path\",
    "name",
    java.io.ByteArrayInputStream@1c99159
);
-> at Service.doSomething(Service.java:13)

¿Qué pasó en la prueba EasyMock, ¿por qué no fue capturado resultado? ¿No se ejecuta el método tienda, pero espera un minuto, era, ¿por qué EasyMock nos miente?

Es porque EasyMock mezclar dos responsabilidades en una sola línea - stubbing y verificación. Por eso, cuando algo está mal es difícil de entender qué parte está causando el fracaso.

Por supuesto, puede dime - sólo cambia la prueba y mover verificar antes afirmación. Vaya, ¿en serio, los desarrolladores deben tener en cuenta un poco de orden mágico inforced al burlarse de marco?

Por cierto, que no ayudará a:

java.lang.AssertionError: 
  Expectation failure on verify:
    store("path", "name", capture(Nothing captured yet)): expected: 1, actual: 0
    at org.easymock.internal.MocksControl.verify(MocksControl.java:111)
    at org.easymock.classextension.EasyMock.verify(EasyMock.java:211)

Aún así, me está diciendo que el método no se ha ejecutado, pero era, sólo que con otros parámetros.

¿Por qué Mockito es mejor? Este marco no se combina dos funciones en un solo lugar y cuando las pruebas fallan, se comprenderá fácilmente por qué.

  

Si nos preocupa el diseño del código, a continuación EasyMock es la mejor opción, ya que proporciona información a usted por su concepto de expectativas

Interesante. He descubierto que 'concepto de expectativas' hace muchos desarrolladores ponen más y más expectativas en las pruebas sólo para satisfacer UnexpectedMethodCall problema. ¿Cómo influye el diseño?

La prueba no debe romperse cuando se cambia de código. La prueba se rompe cuando la función deja de funcionar. Si a uno le gusta las pruebas a romperse cuando sucede cualquier cambio de código sugiero escribir una prueba que afirma la suma de comprobación MD5 del fichero java:)

No creo que debería estar demasiado preocupado por esto. Tanto EasyMock y Mockito pueden configurarse para ser 'estricto' o 'agradable' la única diferencia es que por defecto EasyMock es estricta wheras Mockito es agradable.

Al igual que con todas las pruebas no hay ninguna regla dura y rápida, necesita la confianza de prueba de equilibrio contra la mantenibilidad. Me suelen encontrar que hay ciertas áreas funcionales o técnicos que exigen un alto nivel de confianza para los que me gustaría utilizar burla 'estrictos'. Por ejemplo, probablemente no sería deseable que la debitAccount () para ser llamado más de una vez! Sin embargo, hay otros casos en los que la maqueta es muy poco más que un trozo para que podamos probar la verdadera 'carne' del código.

En los primeros días de la compatibilidad API de vida de Mockito era un problema, pero más herramientas ahora son compatibles con el marco. Powermock (un favorito personal) tiene ahora una extensión Mockito

Yo prefiero Mockito para ser honesto. estado utilizando EasyMock con unitils y la combinación de ambos oftenly resulta en excepciones como IllegalArgumentException: no una interfaz así como MissingBehaviorExceptions. En ambos casos, sin embargo el código y el código de prueba están perfectamente bien. Al parecer, el MissingBehaviorException era debido al hecho de que los objetos creados con burlado de createMock (usando classextentions !!) hicieron producir este error. Al utilizar @Mock lo hizo el trabajo! No me gusta ese tipo de comportamiento engañoso y para mí eso es una clara indicación de que los desarrolladores no saben lo que están haciendo. Un marco bien siempre debe ser fácil de usar y no ambigua. El IllegalArgumentException también se debió a algunos de los componentes internos se mezclan EasyMock. Además, la grabación no es lo que yo quiero hacer. Quiero probar si mi código de lanza excepciones o no y que devuelve los resultados esperados. Que en combinación con la cobertura de código es la herramienta adecuada para mí. No quiero que mis pruebas para romper cada vez que pongo 1 línea de código por encima o por debajo de la anterior, ya que mejora el rendimiento más o menos. Con Mockito no es ningún problema. Con EasyMock, resultará pruebas a fallar a pesar de que el código no está roto. Eso es malo. Cuesta tiempo, por lo tanto dinero. Que desea probar para el comportamiento esperado. Es lo que realmente importa el orden de las cosas? Supongo que en raras ocasiones en que posiblemente encuentre. Uso EasyMock a continuación. En otro caso, creo que va a pasar mucho menos tiempo usando Mockito para escribir sus pruebas.

Saludos cordiales Lawrence

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top