¿Realmente vale la pena probar un cliente API?

38

Esto es algo que me preocupa desde hace un tiempo. ¿Realmente vale la pena probar un cliente API?

Digamos que está creando una pequeña clase para abstraer las llamadas a una API REST de la tienda de mascotas. La tienda de mascotas es una API muy simple y tiene un conjunto básico de métodos:

  • listProducts()
  • getProductDetails(ProductID)
  • addProduct(...)
  • removeProduct(ProductID)

Al probar esto, tendríamos que crear un servicio simulado o simular las respuestas. Pero eso parece excesivo; Entiendo que queremos asegurarnos de que nuestros métodos no dejen de funcionar a través de errores tipográficos / sintácticos, pero dado que estamos escribiendo funciones que llaman métodos remotos y luego estamos creando respuestas falsas de esos métodos remotos, parece que una pérdida de esfuerzo y que estamos probando algo que realmente no puede fallar. Peor aún, si el método remoto cambia, nuestras pruebas unitarias pasarán mientras falla el uso de producción.

Estoy bastante seguro de que me falta algo, o tengo el extremo equivocado del palo, o no veo la madera para los árboles. ¿Alguien puede ponerme en el camino correcto?

Phillip B Oldham
fuente
1
Si esto no fuera una API tan simple con métodos básicos, ¿te sentirías diferente? Incluso un cobertizo tiene que resistir la nieve.
JeffO

Respuestas:

31

El trabajo de un cliente API remoto es emitir ciertas llamadas, ni más ni menos. Por lo tanto, su prueba debe verificar que emite esas llamadas, ni más ni menos.

Claro, si el proveedor de API cambia la semántica de sus respuestas, entonces su sistema fallará en la producción. Pero eso no es culpa de su clase de cliente; es algo que solo se puede atrapar en las pruebas de integración. Al confiar en un código que no está bajo su control, ha renunciado a la capacidad de verificar la corrección a través de pruebas internas; fue una compensación, y este es el precio.

Dicho esto, probar una clase que consiste solo en delegaciones a otra clase puede ser de baja prioridad, porque existe un riesgo comparativamente pequeño de errores complejos. Pero eso se aplica a cualquier clase que consista solo en frases uniformes, no tiene nada que ver con llamar al código de otro proveedor.

Kilian Foth
fuente
Mmm, no estoy seguro si estoy de acuerdo. Puede probar que foo()se llama antes bar(), pero eso no significa que llamar foo()antes bar()sea ​​lo correcto; una prueba unitaria como esa pasaría incluso si el código es incorrecto. Y si eso es todo lo que el cliente está haciendo, configurar los simulacros que verifican si foo()se llama antes bar()es relativamente problemático para algo que puede verificarse con una mirada rápida al código del cliente.
Doval
1
Puede probar que un add()método agrega dos números correctamente, pero eso no significa que sumar sea lo correcto en este punto del algoritmo: la add()prueba unitaria tendrá éxito aunque su programa esté equivocado. Si es algo incorrecto, entonces su levenshteinDistance()método es el culpable, no el add()método. Esto es exactamente lo mismo. El punto de tener el código separado en métodos es siempre que cada método solo tiene que preocuparse por obtener una cosa correcta.
Kilian Foth
3
¡Ahora veo dónde estamos en desacuerdo! Si confía en una tienda de mascotas externa, para mí esto significa que su sistema termina en el límite HTTP, por lo tanto, las llamadas REST emitidas son salidas y están sujetas a pruebas. Si considera que la tienda de mascotas es parte de este módulo, entonces sí, el patrón de las llamadas emitidas es un detalle de implementación, y una prueba de unidad no tiene por qué prescribir nada sobre ellas.
Kilian Foth
2
"Por lo tanto, su prueba debería verificar que emite esas llamadas" Creo que esa es la perspectiva que no veía. ¡Gracias!
Phillip B Oldham
1
Entonces, por ejemplo, ¿mi prueba unitaria podría verificar que, dados ciertos parámetros, el cuerpo de la solicitud que se trata de ejecutar es el correcto?
Maria Ines Parnisari
9

Respuesta corta:

Todos los métodos deben ser probados en unidades.

Respuesta larga:

Sí. Vale la pena.

Estas son algunas cosas que las pruebas unitarias en esos métodos de llamada a la API deben probar:

  • Que está pasando parámetros correctos o bien formados a las llamadas API.
  • Que está respondiendo en consecuencia a ciertos tipos de datos devueltos por las API (simuladas o no), por ejemplo, tal vez cuando la API devuelve una cadena vacía, su método debería devolver un valor predeterminado (solo un ejemplo)
  • Que los métodos de llamada se comporten correctamente cuando las llamadas a la API producen un error

Esas son las cosas que hace el método llamado que pueden aislarse de mi burlarse del servicio API, y que al probarlas bien, le aseguramos que los errores no se originan por un error en el código del cliente que llama a la API.

Tulains Córdova
fuente
Dices "burlado o no" ... entonces, ¿está bien probar con la API real? ¿Puedo llamarlo una prueba de integración aunque parezca una prueba unitaria? ¿O hay otra cosa para llamar a esto? Me encantaría probar que mi contenedor API hace lo que dice que hace, de alguna manera ...
Dan Rosenstark
1
@DanRosenstark Supongo que en el caso de que el servicio API no se esté burlando, es una prueba de integración.
Tulains Córdova
¿No sabría en 5 segundos si está recuperando los datos correctamente cuando realiza una llamada real a la API? Dado que los simulacros de API no son llamadas reales, la única forma en que fallarían sería si cambiaran el API ... en ese caso, sus pruebas simuladas pasarían pero las llamadas reales fallarían. Parece inútil
MattE
5

Estas no serían pruebas unitarias porque está probando la entrada y salida de su sistema, más como pruebas de integración limitadas.

Sea muy cauteloso cuando diga "parece una pérdida de esfuerzo y estamos probando algo que realmente no puede fallar" : puede fallar, fallará, probablemente fallará de una manera que no puede anticipar, el las fallas serán peores si no tiene pruebas establecidas.

El error que está cometiendo aquí tiene que ver con la invención de las ruedas: hacer llamadas a servicios remotos y API es un escenario muy común, por lo que hay algunas herramientas bastante buenas para ayudarlo a probar eso. La última vez que estaba trabajando en una aplicación que se conectaba a servicios remotos, utilicé SoapUIque podría ver un servicio y realizar llamadas simuladas a ese servicio o comportarse como una copia local del servidor con el que puede realizar llamadas de prueba y realizar un seguimiento de las solicitudes y respuestas. La instalación tardó unos minutos y, de la misma manera, la actualización remota fue muy rápida. No lo he usado en un escenario REST, pero incluso si no funciona bien para eso (o tal vez alguien esté leyendo esta respuesta en el futuro cuando existan mejores herramientas), debería poder encontrar una herramienta que pueda simularse un servicio para usted y cuando llegue el momento de implementar su código, se alegrará de haberlo hecho.

glenatron
fuente