Formando “gramáticas” de Mockito

Mockito parece un marco de burla / burla 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 comunes usados ​​en las pruebas incluyen:

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

Cuando ve ejemplos de Mockito en práctica, ve código como:

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

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

Cuándo / Entonces: cuándo (suMétodo ()), luegoVuelva (5);

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

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

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

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

Lo que me estoy ahogando es cómo seleccionar el patrón correcto / combinación de llamadas de método 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 ayudar a 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!

Mockito a menudo tiene varias formas de hacer las cosas.

Me encuentro usando principalmente:

 // 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(); 

Descubrí que puedo hacer el 95% de lo que necesito con estos tres tipos de llamadas.

Además, ¿qué versión de Mockito estás usando? Los constructos “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 implements Answer { public T answer(InvocationOnMock invocation) { return invocation.getArguments()[0]; } } when(object.method(7)).thenAnswer(new ReturnFirstArg()); 

Hay varias desventajas para las when/thenReturn , when/thenThrow y when/then . Por ejemplo,

  • En el caso de when/thenReturn , si el tipo de devolución es genérico con un comodín y desea devolver un simulacro del mismo tipo, no podrá evitar una advertencia de comstackción.
  • No puede usar when/thenThrow y when/then para un método nulo.
  • No puede usar estas syntax en espías de Mockito.
  • Solo puede llamar when una vez para cada combinación de objeto, método y argumentos simulados, a menos que invoque reset en el simulacro.
  • Las llamadas múltiples veces para una combinación de objeto y método simulados, cuando usa argumentos de argumento, pueden generar problemas.

Encuentro estos casos difíciles de recordar. Por lo tanto, en lugar de intentar realizar un seguimiento de cuándo y when/then volverán las syntax when/thenThrow y when/then , prefiero evitarlas por completo, a favor de doReturn/when , doThrow/when y doAnswer/when alternativas Es decir, dado que ocasionalmente necesitará doReturn/when , doThrow/when y doAnswer/when , y SIEMPRE puede usar estos métodos, no tiene sentido aprender cómo usar when/thenReturn , when/thenThrow y when/then

Tenga en cuenta que doReturn , doThrow y doAnswer se pueden encadenar juntos de la misma manera 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 a 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 comstackción que comprueba 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 es una buena práctica de Mockito. Otros usuarios de Mockito no están de acuerdo.

De hecho, las cosas parecen mucho más simples de lo que pensabas

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

Verificar :

Para poder usar Mockito, debes entender una filosofía básica de Mockito: Stubbing and Verification está separada. 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 reactjsrá 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).

Cuándo / Luego, Dado / Will :

Luego viene a las familias “Cuándo” y “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 el caso normal, usamos principalmente when(xxx).then(...) (y given(...).will(...) ). Sin embargo, hay algunos casos en que la syntax 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 va a comstackrse. Como solución, se crea una syntax alternativa de Do / When para que pueda escribir la línea anterior como doThrow(anException).when(mockObj.voidMethod())