Mocking REST services con SOAPUI y Postman[:en]Mocking servicios REST con SOAPUI en modo servidor

[:es]El prototipado de servicios es una potente herramienta para acelerar el desarrollo de software, más aún cuando existen dependencias de terceros o cuando simplemente las líneas de tiempo no se cruzan y la gestión de pre-requisitos se convierten en caos y búsqueda de culpables.

La premisa a postular acá, es que sin importar si los servicios (dependencias) con que me estoy integrando están desarrollados  o no, siempre debe existir una capa de “simulación controlada”, que además de servir de base para las pruebas automatizadas, permita validar condiciones de borde, reproduciéndolas fácilmente de manera controlada.

Existen un número importante de herramientas/frameworks que permiten hacer el llamado “mocking”, en nuestra experiencia, las más útiles son las menos invasivas, que al cambiar algo mínimo (como una URL o un parámetro de ambiente), ejecuten un plan simulado o un escenario real.

Al trabajar con servicios web (SOAP/REST) una de las herramientas más versátiles para las pruebas funcionales es SOAPUI, que en su versión OpenSource es suficiente para el objetivo que queremos lograr. Este POST incluye algunas de las prácticas más comunes que seguimos para su implementación, así como algunas de sus ventajas entre las que es importante destacar:

  1. Funciona tanto para un modelo simulado como para conectarse a servicios reales.
  2. El archivo de proyecto es un xml que puede ser versionado fácilmente. Además que el principio asociado a esto es que su edición sea colaborativa.
  3. Se pueden incluir conjuntos de test para un modelo automatizado.
  4. Iniciar el Mock Server puede hacerse mediante la interfaz de usuario como por línea de comandos (ver este post).
  5. El scripting dentro de los mocking es Groovy.

Algunas Prácticas (Sin importar el orden)

  1. Definir múltiples endpoints de acuerdo a los ambientes que se desean probar (show service viewer). Si tienes un nombre de contexto mucho mejor. service-endpoints
  2. Agregar los recursos que se puedan agrupar a recursos base.
    recursos
  3. Generar el Mock Service después de tener los recursos ya creados, así se crearán todos los mockings de una sola vez.
    mockservices
  4. Editar los headers de las respuestas de acuerdo al caso, en muchas ocasiones se requiere prevenir problemas con CORS (Cross-origin resource sharing) para consumir los servicios independiente al origen. Usar los siguientes con discresión (recordando que propósito principal aqui son las pruebas. No usar en servicios reales).
    headers
  5. Definir diferentes respuestas asociadas a un servicio para seleccionar la adecuada respecto a una entrada.
    response
  6. Puedes usar Scripting (Groovy) para determinar a cual respuesta se debe redireccionar. Aquí un ejemplo que recibe y retorna un json, se toman decisiones basado en el contenido para elegir una respuesta predefinida, la que también puede ser modificada dinámicamente con en el caso 3 de nuestro if.

    [code language=”groovy” highlight=”5,9,18″]
    def slurper = new groovy.json.JsonSlurper()
    def jsonReq = slurper.parseText(mockRequest.requestContent) // Entrada es un json
    log.info jsonReq.userIde
    if (jsonReq.userId == "1") {
    return "sessionNOK" // Retorna una de las respuestas definidas en el mockResponses
    }
    if (jsonReq.userId == "3") {
    sleep (8000) // Lo uso para generar timeouts de la aplicación a propósito
    return "sessionOK"
    }
    else if (jsonReq.userId == "4") { // Caso donde manipulo la salida basado en un parámetro como fecha
    use( groovy.time.TimeCategory ) { //Utilidades de fecha en groovy
    currentDate = new Date()
    after30Mins = currentDate + 5.minutes // Sumando 5m a la fecha actual para retornarlo como parámetro
    }
    dateExpiring = after30Mins.format("yyyy-MM-dd’T’HH:mm:ss’Z’", TimeZone.getTimeZone("UTC")) //Formato ISO 8601
    requestContext.responseMessage = ‘{"id": "0","desc": "OK","result":{"token":"ABCDE123456789", "dateEnd":"’+dateExpiring+’"}}’
    return "expiring" // redirige a este tipo de respuesta, que a su vez usa ${responseMessage} como salida.
    }
    else {
    return "sessionOK"
    }
    [/code]

    Expiring response:
    expiring

  7. Considerando que el archivo de proyecto es xml codificado en UTF-8 hace sentido que los datos que usemos se representen con la codificación adecuada y no tengamos conflicto cuando el servidor mock está arriba. Adicionalmente se recomienda agregar explicitamente el header Accept-Charset: utf-8. Ejemplo de mensaje json codificado utf-8 con acentos.

    [code language=”javascript”]
    { "resultado":"Buenos d\u00EDas UTF8" }
    [/code]

  8. Usar los http codes para emular problemas en las respuestas de los servicios resulta bastante útil para condiciones de borde. Ejm
    401
  9. Una vez tengas los servicios simulados, basta con iniciar el servicio desde la misma interfaz de SoapUI. Luego de esto necesitas probar que todo esto funcione bien…
    startmock

Una de las herramientas que mejor se complmenta con los servicios mock creados en SOAPUI, es Postman, plugin de chrome que también funciona como aplicacion independiente.  Te recomiendo usar Postman para validar todos los servicios creados en los pasos anteriores, Postman valida las salidas mucho mejor que SOAPUI, así que es más fácil encontrar un error (un corchete mal cerrado por ejemplo) en la respuesa de salida. Además permite crear diferentes casos de prueba, almacenar las entradas y el formato de intercambio (almacenamiento) es también un xml que puede ser versionado.

Algunos consejos con Postman

  1. Usar un archivo base json (Collection) que sea incremental, colaborativo y versionado. Este archivo debe ser importado constantemente en la herramienta y a su vez exportado (sobre-escribiendo la versión inicial) cuando haya cambios.
    postman-import-export
  2. Agrupar por carpetas los servicios similares.
  3. Parametrizar los endpoint de tal manera que las URL sean fácilmente intercambiadas entre distintos ambientes. Esta configuración, soporta http y https usando los puertos respectivos (por defecto 80 y 443 respectivamente), además se configura de esta manera buscando soportar nombres de contexto vacío (si los hubiese).
    Formato:{{protocol}}://{{server}}:{{port}}/{{context}}myServiceName
    endpoint1
  4. Los ambientes se parametrizan en la sección “manage environments” que permite almacenar configuraciones por ambiente independientes.environment
  5. Cada ambiente se almacena además como un archivo de configuración json diferente (no olvides exportarlo y versionarlo). Los valores se reemplazan dinámicamente en las variables del contexto de prueba cuando se llama el servicio (endpoint clasificado)
    env-local

Bien, esto es apenas una introducción de todo lo que se puede lograr con SoapUI como herramienta de generación de respuestas simuladas y controladas en nuestros ambientes de desarrollo. La extensión, cobertura, desarrollo de mock services y generación conjuntos de test sobre los mismos, dependerán del contexto y el objetivo que queremos lograr. Pero siempre, será buena idea lograr aislarnos de dependencias fuertes como lo son servicios web.

[feather_share show=”twitter, facebook, linkedin” hide=”reddit, pinterest, tumblr, google_plus, mail” size=”24″][:]