Unidad probando un método vacío

13

Para corregir un error en una aplicación, modifiqué un método llamado postLoginagregando una llamada a un método existente llamado getShoppingCart.

Código

protected void postLogin() {
  getShoppingCart();
}

Sin embargo, no estoy seguro de cuál es la mejor manera de escribir una prueba unitaria postLogin.

Enfoque 1

Utilice verificar de Mockito para verificar simplemente que se llamó al método.

verify(mock).getShoppingCart();

Enfoque 2

Pruebe el efecto secundario de la llamada al método obteniendo el valor del carrito de compras del usuario.

AssertNotNull(user.getShoppingCart());

¿Es un enfoque mejor que el otro?

A_B
fuente
1
lo que haga que la prueba sea más fácil de entender y mantenga el código limpio. Si no está seguro del diseño de la prueba, eso PODRÍA ser también una señal de que el diseño del código está desactivado. Asegúrese de hacer estas preguntas: " ¿POR QUÉ al agregar esa llamada al método se soluciona el error? ¿Es esta la forma CORRECTA de solucionar este error?"
Caleb
8
A menos que su getShoppingCart()método tenga efectos secundarios, no necesita probar que se llama. Si tiene efectos secundarios, debería cambiar su nombre porque los getXXX()métodos convencionales deberían ser idempotentes.
Jules
@Jules getNextValue? Podría decirse que alguien podría decir "No lo llames getter; cambia el nombre a nextValue", pero lo he visto getNextantes. Quizás un mejor ejemplo sería un objeto que representa un electrón; ¿Qué pasa cuando llamo getPosition? O peor,getPosition(); getVelocity();
Aaron

Respuestas:

18

Por lo general, preferiría el método 2.

¿Por qué? Porque desea postLogincambiar algún estado de su sistema, pero la forma en que lo logra (y qué métodos llama internamente para esto) es simplemente un detalle de implementación, nada sobre lo que su prueba unitaria debe hacer suposiciones. Así que mejor haz tu prueba solo verificando el estado final.

Doc Brown
fuente
4

Cambiaría getShoppingCart por algo como initializeShoppingCart, el propósito del método debería ser claro para quien lo lea sin la necesidad de verificar qué hace el método y los efectos secundarios como este pueden causar un comportamiento sorprendente para los usuarios del método.

Si getShoppingCart está en otra clase y ya está probado en la unidad, usaría el enfoque 1; no es necesario volver a probar lo que ya está probado. En este caso, estamos seguros de que getShoppingCart funciona correctamente y solo queremos asegurarnos de que se llame desde postLogin, por lo que si alguien en el futuro elimina esta llamada, la prueba fallará.

Si getShoppingCart es un método privado que no se puede probar por sí solo, entonces usaría el enfoque 2, para asegurarme de que cuando se llame a postLogin, la funcionalidad deseada de getShoppingCart se realice como se esperaba.

Nastya S
fuente
1

Al probar una llamada de función (nula o no) que tiene un efecto secundario, es más completo probar que el efecto secundario no solo ocurre, sino verificar que el efecto secundario (salida del sistema o cambio de estado) sea el deseado.

hotpaw2
fuente
1
Si bien esto es cierto, también vale la pena considerar que los detalles del efecto secundario que ocurre podrían ser parte del estado interno de algún otro módulo, y que al verificar esos detalles estarías acoplando tu prueba no solo al módulo que está probando pero también ese otro módulo, que podría conducir a pruebas frágiles si es probable que esos detalles cambien. Burlarse de la interfaz entre módulos ayuda a prevenir este problema.
Jules
0

No discutiré su diseño, pero en su caso elegiría el primer enfoque porque la prueba unitaria es para probar qué métodos hacen técnicamente independientemente de su trabajo en el dominio, es decir, ¿qué hace su método postLogin? Técnicamente llama, getShoppingCardasí que tienes que probar que realmente está llamando getShoppingCard, también crearía otra prueba para getShoppingCardprobar lo que hace y si tiene efectos secundarios, lo comprobaré dentro de esa nueva prueba.

La VloZ Merrill
fuente
0

Tienes un error en postLogin. Entonces, lo primero que debe hacer es crear una prueba unitaria que al llamar a postLogin sin el conjunto de información esperado "fallará".

A partir de la idea anterior, otra alternativa de las 2 propuestas es inyectar la información sobre el carrito de compras como parámetro. Si no tiene la información correcta, lanza una excepción no verificada. Esto dejará en claro que sin los detalles correctos, su método está condenado.

Esto requerirá un pequeño cambio en el que el cliente que llama al postLogin en este momento también debe pasar la información del carrito de compras. Para mí, esto sigue siendo coherente ahora que ves que están acoplados. Este acoplamiento lo realizará la persona que llama.

Entonces ni siquiera necesitaría probar getShoppingCart dentro de postLogin porque el método real bajo prueba es postLogin. Es el que tiene el error y el único que requiere una corrección y validación adecuadas. Con la dependencia inyectada, podrá probarla fácilmente en diferentes condiciones y confirmar que no se produce ningún error.

gumol
fuente