2012-07-13 15 views
25

Mockito parece ser un marco de anotación/burlarse bastante dulce para Java. El único problema es que no puedo encontrar ninguna documentación concreta sobre las mejores formas de usar su API. Los métodos más comunes utilizados en las pruebas incluyen:Formando las "gramáticas" de Mockito

doXXX(???) : Stubber 
when(T) : OngoingStubbing 
then(T) : OngoingStubbing 
verify(???) : T 
given(T) : BDDOngoingStubbing 
willXXX(???) : BDDStubber 

Cuando vea ejemplos de Mockito en la práctica, se ve un código como:

when(yourMethod()).thenReturn(5); 

De todos los documentos que he leído, he identificado varios " patrones "de las gramáticas de Mockito" obtenidos de la conexión en cadena de estas llamadas a métodos como el ejemplo anterior. Algunos patrones comunes que he encontrado son:

cuando/luego:. cuando (yourMethod()) thenReturn (5);

Given/Will: dado (yourMethod()). WillThrow (OutOfMemoryException.class);

Do/When: doReturn (7) .when (yourMock.fizzBuzz());

Will/Given/Do: willReturn (any()). Given (yourMethod()). DoNothing();

Verificar/Do: verificar (yourMethod()). DoThrow (SomeException.class);

Lo que me estoy ahogando es cómo seleccionar el patrón correcto/combinación de llamadas a métodos para modelar mis casos de prueba. Parece que puedes encadenarlas en combinaciones aparentemente infinitas y no estoy seguro de cuál es el patrón correcto para cada problema.

¿Puede algún Mockito Guru arrojar algo de luz sobre qué patrones/combinaciones de métodos de Mockito se utilizan para qué tipos de casos de prueba (y por qué)? ¡Gracias por adelantado!

Respuesta

8

Mockito a menudo tienen varias formas de hacer las cosas.

me encuentro con la mayoría:

// Setup expectations 
when(object.method()).thenReturn(value); 
when(object.method()).thenThrow(exception); 
doThrow(exception).when(object.voidMethod()); 


// verify things 
verify(object, times(2)).method(); 
verify(object, times(1)).voidMethod(); 

He descubierto que puedo hacer el 95% de lo que tengo que con estos tres tipos de llamadas.

Además, ¿qué versión de Mockito estás usando? las construcciones "given" y "will" no están presentes en la última versión (1.9.0+)

Sin embargo, hay casos en los que deseo que el valor devuelto o la excepción respondan a la entrada. En este caso, puede usar la interfaz Answer para inspeccionar los argumentos del método y devolver un valor apropiado.

public class ReturnFirstArg<T> implements Answer<T> { 
    public T answer(InvocationOnMock invocation) { 
     return invocation.getArguments()[0]; 
    } 
} 

when(object.method(7)).thenAnswer(new ReturnFirstArg<Integer>()); 
+1

+1 También está la sintaxis [BDD] (http://mockito.googlecode.com/svn/branches/1.8.0/javadoc/org/mockito/BDDMockito.html). –

+0

@Garret Hall: gracias por el puntero. Nunca he usado esta clase, pero sospecho que es porque nunca he tenido que :) – Matt

+0

¿Estás seguro de que 'given' y' will' no están en Mockito 1.9.0 y versiones posteriores? Creo que están en la clase 'BDDMockito'. –

8

Las cosas, de hecho, se ve mucho más sencillo de lo que pensaba

REF: http://static.javadoc.io/org.mockito/mockito-core/2.7.12/org/mockito/Mockito.html

Compruebe:

Para utilizar Mockito, es necesario entender una filosofía básica de Mockito: Stubbing y verificación están separados. Por lo tanto, el "Verify/Do" que mencionaste está de hecho haciendo el trabajo de "Verificación", mientras que las otras 4 "gramáticas" son para el troquelado. Stubbing define cómo reaccionará el objeto simulado en diferentes situaciones. La verificación es para asegurarse de que se invoque lo que se simula como se esperaba, en una invocación previa al sistema bajo prueba (SUT).

cuando/luego, Dada/Will:

Entonces vienen al "cuándo" y las familias "dado". Simplemente puede tratarlos como alias uno del otro. La familia "Given" se agrega en Mockito 1.8.x para que parezca más alineada con las prácticas de BDD.

doXXX:

En caso normal utilizamos sobre todo when(xxx).then(...) (y given(...).will(...)). Sin embargo, hay algunos casos en que la sintaxis no funciona. El caso más obvio es cuando el tipo de devolución del método stubbed es nulo. En tal caso, when(mockObj.voidMethod()).thenThrow(anException) no se compilará. Como solución, una sintaxis alternativa de Do/Cuando se crea, por lo que puede escribir la línea anterior como doThrow(anException).when(mockObj.voidMethod())

+0

Gracias @Adrian: su enlace está roto – IAmYourFaja

+0

Enlace fijo. De hecho, es solo el enlace "Documentación" de mockito.org –

22

hay varios inconvenientes a los when/thenReturn, when/thenThrow y when/then sintaxis. Por ejemplo,

  • En el caso de when/thenReturn, si el tipo de cambio es un genérico con un comodín , y que desea devolver una maqueta del mismo tipo, que será incapaz para evitar una advertencia de compilación.
  • No puede usar when/thenThrow y when/then para un método nulo.
  • No puede usar estas sintaxis en espías de Mockito.
  • Solo puede llamar al when una vez por cada combinación de objeto simulado, método y argumentos, a menos que llame al reset en el simulacro.
  • Llamar a when varias veces para una combinación de objeto 0 método de simulación , cuando usa argumentos compatibles, puede ocasionar problemas.

Encuentro estos casos difíciles de recordar. Así que en lugar de tratar de mantener un registro de cuando los when/thenReturn, when/thenThrow y when/then sintaxis serán y no funcionarán, prefiero evitarlos por completo, a favor de las alternativas doReturn/when, doThrow/when y doAnswer/when. Es decir, dado que ocasionalmente necesitará doReturn/when, doThrow/when y doAnswer/when, y SIEMPRE puede usar estos métodos, no tiene sentido aprender a usar when/thenReturn, when/thenThrow y when/then.

Tenga en cuenta que doReturn, doThrow y doAnswer se pueden encadenar juntos en la misma forma que thenReturn, thenThrow y then. Lo que no tienen es una opción para devolver varios valores (o lanzar varias excepciones, o ejecutar varias respuestas) dentro de una sola llamada al doReturn, doThrow y doAnswer. Pero me parece que necesito hacer esto tan pocas veces, que en realidad no importa.

Hay una desventaja más para doReturn, que considero insignificante. No obtiene el tiempo de compilación comprobando el tipo de su argumento, como lo hace con when/thenReturn. Entonces, si obtiene el tipo de argumento incorrecto, no lo sabrá hasta que ejecute su prueba. Francamente, no me importa.

En resumen, he estado usando Mockito durante más de dos años, y considero que el uso consistente de doReturn, doThrow y doAnswer ser una buena práctica Mockito. Otros usuarios de Mockito no están de acuerdo.

+1

, probablemente solo mi opinión personal, la mayor ventaja de 'when/then' para mí es su legibilidad. Es mucho más fluido para leer en comparación con 'doXxx/when'. –

+1

@AdrianShum Entiendo tu punto; realmente lo hago Pero encuentro que las dos formas son igualmente legibles. Creo que finalmente se reduce a lo que estás acostumbrado. Para un principiante Mockito que comienza, no dudo en recomendar los formularios do/when. –

+1

Estoy de acuerdo con @ david-wallace. La legibilidad es muy subjetiva; la consistencia no es La seguridad de tipo de tiempo de compilación no es importante aquí ya que su prueba la encontrará más tarde. Los [documentos de Mockito] (http://mockito.googlecode.com/svn/branches/1.6/javadoc/org/mockito/Mockito.html#doReturn%28java.lang.Object%29) deberían modificarse en este punto. – cdunn2001