Mockito: diferencia entre doReturn () y cuándo ()

Actualmente estoy en el proceso de usar Mockito para burlar mis objetos de capa de servicio en una aplicación Spring MVC en la que quiero probar los métodos de mi Controlador. Sin embargo, como he estado leyendo sobre los detalles de Mockito, he encontrado que los métodos doReturn(...).when(...) es equivalente a when(...).thenReturn(...) . Entonces, mi pregunta es de qué sirve tener dos métodos que hacen lo mismo o cuál es la sutil diferencia entre doReturn(...).when(...) y when(...).thenReturn(...) ?

Cualquier ayuda sería apreciada.

Las dos syntax para stubbing son aproximadamente equivalentes. Sin embargo, siempre puede usar doReturn/when for stubbing; pero hay casos en los que no se puede usar when/thenReturn . Tropezar con métodos vacíos es uno de estos. Otros incluyen el uso con espías de Mockito y el troquelado del mismo método más de una vez.

Una cosa que when/thenReturn le da, que doReturn/when does not, es la verificación de tipo del valor que está devolviendo, en tiempo de comstackción. Sin embargo, creo que esto casi no tiene valor; si tiene el tipo equivocado, lo sabrá tan pronto como ejecute la prueba.

Recomiendo usar solo doReturn/when . No tiene sentido aprender dos syntax cuando uno lo hará.

Es posible que desee consultar mi respuesta en Forming Mockito “gramáticas” , una respuesta más detallada a una pregunta muy relacionada.

Ambos enfoques se comportan de manera diferente si utiliza un objeto espía (anotado con @Spy ) en lugar de un simulacro (anotado con @Mock ):

  • when(...) thenReturn(...) realiza una llamada al método real justo antes de que se devuelva el valor especificado. Entonces, si el método llamado arroja una excepción, tienes que tratar con ella / simularla, etc. Por supuesto, aún obtienes tu resultado (lo que defines en thenReturn(...) )

  • doReturn(...) when(...) no llama al método en absoluto .

Ejemplo:

 public class MyClass { protected String methodToBeTested() { return anotherMethodInClass(); } protected String anotherMethodInClass() { throw new NullPointerException(); } } 

Prueba:

 @Spy private MyClass myClass; // ... // would work fine doReturn("test").when(myClass).anotherMethodInClass(); // would throw a NullPointerException when(myClass.anotherMethodInClass()).thenReturn("test"); 

El Mockito javadoc parece indicar por qué usar doReturn() lugar de when() Use doReturn () en las raras ocasiones en que no se puede usar Mockito.when (Object).

Tenga cuidado de que Mockito.when (Object) siempre se recomiende para stubbing porque es un tipo de argumento seguro y más legible (especialmente al anotar llamadas consecutivas).

Aquí están las raras ocasiones en que doReturn () es útil:

1. Al espiar objetos reales y llamar a métodos reales en un espía trae efectos secundarios

List list = new LinkedList(); List spy = spy(list);

// Imposible: el método real se llama para que spy.get (0) arroje IndexOutOfBoundsException (la lista esté vacía)

when(spy.get(0)).thenReturn("foo");

// Tienes que usar doReturn () para stubbing: doReturn("foo").when(spy).get(0);

2. Anulando un trozo de excepción previo:

when(mock.foo()).thenThrow(new RuntimeException());

// Imposible: se llama al método foo () stubbed de excepción para que se genere RuntimeException. when(mock.foo()).thenReturn("bar");

// Tienes que usar doReturn () para copiar:

doReturn("bar").when(mock).foo(); Los escenarios anteriores muestran una compensación de la elegante syntax de Mockito. Tenga en cuenta que los escenarios son muy raros, sin embargo. El espionaje debe ser esporádico y anular excepciones, es muy raro. Sin mencionar que, en general, el borrado definitivo es un olor a código potencial que señala demasiado punteado.

La última alternativa se usa para métodos en simulaciones que vuelven void .

Por favor, eche un vistazo, por ejemplo, aquí: Cómo hacer simulacros a métodos vacíos con mockito

Continuando con esta respuesta , hay otra diferencia que si quiere que su método devuelva diferentes valores, por ejemplo, cuando se llama por primera vez, cuando se llama por segunda vez, etc., entonces puede pasar valores, por ejemplo …

 PowerMockito.doReturn(false, false, true).when(SomeClass.class, "SomeMethod", Matchers.any(SomeClass.class)); 

Por lo tanto, devolverá false cuando se llame al método en el mismo caso de prueba y luego volverá falso y finalmente será verdadero.

“simulacro” puede simular un objeto en lugar de crearlo; “espía” puede crear un objeto real con parámetros reales. Cuando hacemos pruebas unitarias, a menudo los usamos. Pero ‘cuando (xxx) .thenReturn (xxx)’ se usa para simulacro y ‘doReturn (xxx) .when (xxx)’ se usa para espiar.