2012-02-22 23 views
6

Al utilizar Mockito, sólo lo uso para burlarse a cabo las dependencias, es decir, mi flujo de trabajo se ve sobre todo como esto:Mockito - Sensación de que yo no uso todo su potencial

tengo una clase con dependencias:

public class C { 
    public C (A a, B b) { 
     this.a = a; 
     this.b = b; 
    } 

    public String fooBar() { 
     return a.foo() + b.bar(); 
    } 
} 

En mi clase de prueba, me burlo a cabo esas dependencias, y les digo que valora a regresar cuando se llama a algunos métodos especificados:

public class CSpec { 
    private A a = mock(A.class); 
    private B b = mock(B.class); 

    @Test 
    public itShouldReturnFooBar() { 
     when(a.foo()).thenReturn("foo"); 
     when(b.bar()).thenReturn("bar"); 

     C c = new C(a, b); 

     assertThat(c.fooBar().isEqualTo("foobar")); 
    } 
} 

(espero que este ejemplo no es demasiado simple o demasiado deriv ed ;-)). Esto funciona bien, me permite probar clases (aquí: C) de forma aislada. Aún así, nunca uso los métodos verify de Mockito ni ninguna de sus características. ¿Está bien/es suficiente usar Mockito de esta manera?

Respuesta

5

La verificación se usaría normalmente para verificar que su C realmente llame a los métodos A.foo() y B.bar(). Por lo tanto, podría agregar

verify(a).foo(); 
verify(b).foo(); 

antes o después de assertThat. No creo que necesita o debería usarlos aquí, pero hay varias situaciones en las que se necesitan que:

  • aob hace algo que no es visible/accesible desde la API pública de C (por ejemplo, la tala)
  • usted está preocupado con el orden de ejecución
  • Usted quiere asegurarse de que sóloa.foo y b.bar métodos se llaman, nada que se le a.foo2
  • Usted podría utilizar esos simulacros como espía de, por lo que la llamada a a.foo haría segundo e luego enrutado al aReal.foo
+1

¿Pero realmente me compra algo? ¿No está revisando el valor devuelto lo suficiente? – helpermethod

+0

¿Qué pasa si su método no devuelve un valor? – blank

+2

En su caso muy simple, sí, pero en muchos casos, verificar que realmente se llama algo durante la ejecución de un método complejo es exactamente lo que quiere. – vertti

1

Sí, no hay ningún problema con esta prueba, está perfectamente bien. El simple hecho de que los stubs se usan hacen que la prueba funcione, si quita o cambia los stubs, la prueba no funcionará.

La adición de declaraciones de verificación solo redundará en redundancias en este tipo de pruebas.

Sin embargo, si desea verificar con precisión los argumentos, el orden o el número de interacciones o algo más, entonces definitivamente desea agregar controles sobre las interacciones entre el objeto evaluado y sus colaboradores.

1

Está bien utilizar Mockito solo de esta manera. Pero si su código se vuelve más complejo, necesita hacer algunas cosas más para que su código sea probado lo más simple posible.

Otro pequeño ejemplo:

public void eitherAorB() { 
    if(somethingIsTrue) { 
     a.doSomething(); 
    } else { 
     b.doSomethingElse(); 
    } 
} 

Es posible que desee asegurarse de que el método esperado se llama en el objeto esperado.

@Test 
public doSomethingShouldBeCalledOnA() { 
    A a = mock(A.class); 
    C c = new C(a, new B()); 

    c.setSomeThingIsTrue(true); 
    eitherAorB(); 

    verify(a).doSomething(); 
} 

@Test 
public doSomethingElseShouldBeCalledOnB() { 
    B b = mock(B.class); 
    C c = new C(new A(), b); 

    c.setSomeThingIsTrue(false); 
    eitherAorB(); 

    verify(b).doSomethingElse(); 
} 

En otros casos, es posible que desee saber qué parámetro se pasó a un método. Para eso necesitas un ArgumentCaptor.

O en algunos casos necesita llamar al método real o usar un objeto real (sin simulacro), por lo que es hora de espiar un objeto y capturar argumentos o verificar el comportamiento.

Así que hay mucho más a Mockito que podría necesitar de vez en cuando.

2

El enfoque verify es particularmente útil en un estilo de programación Tell Don't Ask.

Considérese la siguiente versión de su clase C:

public class C { 
    public C(A a, B b, CListener L) { ... } 
    ... 
    public void foobar() { 
    String result = complexPrivateMethod(a, b); 
    L.fooBarred(result); 
    } 
} 

Por lo tanto, en lugar de calcular el resultado, usted informar a alguna parte interesada (por ejemplo, una interfaz de usuario) sobre el resultado.

foobar Para probar este momento, probablemente desea verificar que el oyente se invoca correctamente:

public class CTest { 
    @Mock CListener mockListener; 
    ... 

    @Test itShouldTellCAboutFooBar() { 
     C c = new C(stubbedA, stubbedB, mockedListener); 
     ... 
     verify(mockedListener).fooBarred("foobar"); 
    } 
} 

Este uso de verify es típico de Test-Driven Development: Ver Freeman & de Growing Object-Oriented Software Guided by Tests Pryce.

Por lo tanto, si desea utilizar el potencial completo de Mockito (la pregunta), lo más importante es adoptar la filosofía de diseño correspondiente en su código.

1

Las respuestas dadas hasta ahora son buenas, pero hay características adicionales que tampoco mencionas. Las anotaciones @Mock, @Spy, @InjectMocks son todas muy útiles. Junto con los métodos verify(...), también existe la clase InOrder para ayudar a verificar el orden de las llamadas a métodos. Y tal vez ya usa los métodos de emparejamiento (<T> any(T t), anyString(), etc.), pero no muestra que use esas instalaciones.

+0

Definitivamente vale la pena mencionar '@ Mock' - hace las cosas más cortas y más legibles. Entonces, la primera línea de su clase de prueba sería '@Mock private A a;' en lugar de 'private A a = mock (A.class);'. –

Cuestiones relacionadas