Pruebas de cliente REST utilizando la herramienta Restito: ¿Qué es Rest Client?

¿Qué es REST?

REST significa "Transferencia de Estado REpresentacional", que es una nueva forma de comunicación entre dos sistemas cualesquiera en un momento dado. Uno de los sistemas se llama "Cliente REST" y el otro se llama "Servidor REST".

Antes de aprender sobre Restito Framework para pruebas de clientes REST, primero aprendamos algunos conceptos básicos.

¿Qué es el cliente REST?

REST Client es un método o herramienta para invocar una API de servicio REST que está expuesta para la comunicación por parte de cualquier sistema o proveedor de servicios. Por ejemplo: si una API está expuesta para obtener información de tráfico en tiempo real sobre una ruta de Google, el software/herramienta que invoca la API de tráfico de Google se denomina cliente REST.

¿Qué es el servidor REST?

Es un método o una API que está expuesta a la comunicación por parte de cualquier sistema o proveedor de servicios. Por ejemplo, Google expone una API para obtener información del tráfico en tiempo real en una ruta determinada.

Aquí, el servidor de Google debe estar en funcionamiento para escuchar cualquier solicitud a la API expuesta de diferentes clientes.

Ejemplo:

Es hora de establecer un escenario completo de extremo a extremo a partir de las definiciones anteriores.

Consideremos una aplicación de reserva de taxis como Uber, ya que una empresa necesita información en tiempo real sobre la situación del tráfico en las rutas en las que se encuentra un vehículo determinado.

Cliente de descanso:

Aquí el cliente es una aplicación móvil de Uber en la que el conductor ha iniciado sesión. Esta aplicación envía una solicitud a la API REST expuesta por Google Maps para obtener datos en tiempo real. Por ejemplo, una solicitud HTTP GET.

Servidor de descanso:

En este ejemplo, Google es el proveedor de servicios y la API de Google Maps responde con los detalles requeridos a la solicitud de la aplicación Uber.

Tanto el cliente como el servidor son igualmente importantes en la comunicación REST.

Aquí, hemos implementado ejemplos para pruebas de automatización solo del Cliente REST. Para probar el servidor REST, consulte https://www.guru99.com/top-6-api-testing-tool.html.

¿Qué es Restito?

Restito es un framework desarrollado por Mkotsur. Es una aplicación liviana que te ayuda a ejecutar cualquier tipo de solicitud HTTP. Puedes usar Restito para probar tus API REST y buscar problemas en tu aplicación o tu red.

¿Cómo probar el cliente REST usando Restito?

Dividiremos el ejercicio en los siguientes 4 pasos:

  1. Cree un cliente HTTP y un método para enviar una solicitud HTTP GET a cualquier punto final del servidor. Por ahora, considere que el punto final es http://localhost:9092/getevents.
  1. Inicie un servidor Restito para escuchar y capturar las solicitudes enviadas al punto final 'getevents' en localhost http://localhost:9092/getevents.
  1. Cree una clase de prueba para probar el cliente anterior. Invoque el método 'sendGETRequest' del cliente HTTP para iniciar una solicitud GET a la API 'getevents'.
  1. Valide la llamada HTTP GET utilizando el marco Restito.

Profundicemos en cada uno de los pasos anteriores.

Paso 1) Cree un cliente HTTP y un método para enviar una solicitud HTTP GET a cualquier punto final del servidor.

========== Se inicia el CÓDIGO JAVA ===========

package com.chamlabs.restfulservices.client;

import java.util.HashMap;
import java.util.Map;

import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.json.JSONObject;

/**
 * This class creates a HTTP Client and has a method to send HTTP GET request: 
 * 		sendGETRequest(..)
 */
public class RestClient {
	/**
	 * Constructor for the  class RestClient	
	 */
	public RestClient() {
		System.out.println("Creating RestClient constructor");
	}

	/**
	 * Method to Send GET request to http://localhost:<<port>>/getevents
	 * @param port
	 * @return true if GET request is successfully sent. False, otherwise.
	 */
	public static boolean sendGETRequest(int port) {
		try {
			HttpClient client = HttpClientBuilder.create().build();
			HttpGet getRequest = new HttpGet("http://localhost:" + port + "/getevents");
			//HttpResponse response = client.execute(request);
			client.execute(getRequest);
			System.out.println("HTTP request is sent successfully."
					+ "Returning True");
			return true;
		} 
		
		catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("Some exception has occurred during the HTTP Client creation."
				+ "Returning false");
		return false;
	}
}

========== CÓDIGO JAVA Termina ===========

Paso 2) Inicie un servidor Restito para escuchar y capturar las solicitudes enviadas al punto final 'getevents' en localhost http://localhost:9092/getevents.

========== Se inicia el CÓDIGO JAVA ===========

package com.chamlabs.restfultesting.util;

import static com.xebialabs.restito.builder.stub.StubHttp.whenHttp;
import static com.xebialabs.restito.semantics.Action.status;
import static com.xebialabs.restito.semantics.Condition.get;
import static com.xebialabs.restito.semantics.Condition.post;
import java.util.List;
import org.glassfish.grizzly.http.util.HttpStatus;
import com.xebialabs.restito.semantics.Call;
import com.xebialabs.restito.server.StubServer;

/**
 * This utility class contains several utility methods like : 
 * 		restartRestitoServerForGETRequests(..)
 * 		restartRestitoServerForPOSTRequests(..) 
 * 		waitAndGetCallList(..)
 * 
 * @author cham6
 * @email: paperplanes.chandra@gmail.com
 * @fork: https://github.com/cham6/restfultesting.git
 *
 */
public class TestUtil {
	
	/**
	 * Utility method to start restito stub server to accept GET requests
	 * @param server
	 * @param port
	 * @param status
	 */
	public static void restartRestitoServerForGETRequests (StubServer server, int port, HttpStatus status)
    {
        // Kill the restito server
        if (server != null) {
            server.stop();
        }
        // Initialize and configure a newer instance of the stub server
        server = new StubServer(port).run();
        whenHttp(server).match(get("/getevents")).then(status(status));
    }
	
	/**
	 * Utility method to start restito stub server to accept POST requests
	 * @param server
	 * @param port
	 * @param status
	 */
	public static void restartRestitoServerForPOSTRequests (StubServer server, int port, HttpStatus status)
    {
        // Kill the restito server
        if (server != null) {
            server.stop();
        }
        // Initialize and configure a newer instance of the stub server
        server = new StubServer(port).run();
        whenHttp(server).match(post("/postevents")).then(status(status));
    }
	
	/**
     * For a given restito stub server, loop for the given amount of seconds and
     * break and return the call list from server.
     * 
     * @param server
     * @param waitTimeInSeconds
     * @return
     * @throws InterruptedException
     */
	public static List<Call> waitAndGetCallList (StubServer server, int waitTimeInSeconds)
        throws InterruptedException
    {
        int timeoutCount = 0;
        List<Call> callList = server.getCalls();
        while (callList.isEmpty()) {
            Thread.sleep(1000);
            timeoutCount++;
            if (timeoutCount >= waitTimeInSeconds) {
                break;
            }
            callList = server.getCalls();
        }
        // Wait for 2 seconds to get all the calls into callList to Eliminate any falkyness.
        Thread.sleep(2000);
        return server.getCalls();
    }


}

========== CÓDIGO JAVA Termina ===========

Paso 3) Cree una clase de prueba para probar el cliente anterior. Invoque el método sendGETRequest del cliente HTTP para iniciar una solicitud GET a la API 'getevents'.

========== Se inicia el CÓDIGO JAVA ===========
import junit.framework.TestCase;

import com.chamlabs.restfulservices.client.RestClient;
import com.chamlabs.restfultesting.util.TestUtil;
import com.xebialabs.restito.semantics.Call;
import com.xebialabs.restito.server.StubServer;
import static org.glassfish.grizzly.http.util.HttpStatus.ACCEPTED_202;
import org.json.JSONObject;
import java.util.List;
import java.util.Map;

/**
 * This class contains several junit tests to validate the RestClient operations like: 
 * 		sendRequest(..)
 * 		sendRequestWithCustomHeaders(..) 
 * 		sendPOSTRequestWithJSONBody(..)
 *
 */

public class RestClientTester extends TestCase {
	
    private static final Integer PORT = 9098;
    private static final Integer PORT2 = 9099;
    private static final Integer PORT3 = 9097;
	
    public RestClientTester() {
    	System.out.println("Starting the test RestClientTester");
    }
    /**
     * Junit test to validate the GET request from RestClient
     * Steps:
     * 		1) Create a stub server using Restito framework and configure it to listen on given port
     * 		2) Invoke the sendGETRequest(..) method of RestClient
     * 		3) Restito captures the matching GET requests sent, if any.
     * 		4) Validate if Restito has captured any GET requests on given endpoint
     * Expected Behavior:
     * 		> Restito should have captured GET request and it should have captured only one GET request.
     * Finally:
     * 		> Stop the stub server started using restito.
     */
	public void testGETRequestFromClient() {
		
		StubServer server = null;
		try {
		//This will start the stub server on 'PORT' and responds with HTTP 202 'ACCEPTED_202'
		TestUtil.restartRestitoServerForGETRequests(server, PORT, ACCEPTED_202);
		
		RestClient.sendGETRequest(PORT);
		
		List<Call> callList = TestUtil.waitAndGetCallList(server, 30);
		assertTrue("GET request is not received from the RestClient. Test failed.", 
				(callList != null) && (callList.size() == 1));
		}
		catch(Exception e) {
			e.printStackTrace();
			fail("Test Failed due to exception : " + e);
		}
		finally {
			if(server != null) {
				server.stop();
            }
		}	
	}

========== CÓDIGO JAVA Termina ===========

Paso 4) Cómo validar la solicitud GET con encabezados y la solicitud POST con el cuerpo usando el marco Restito.

========== Se inicia el CÓDIGO JAVA ===========

/**
     * Junit test to validate the GET request with headers from RestClient
     * Steps:
     * 		1) Create a stub server using Restito framework and configure it to listen on given port
     * 		2) Invoke the sendGETRequestWithCustomHeaders(..) method of RestClient
     * 		3) Restito captures the matching GET requests sent, if any. 
     * 		4) Validate if Restito has captured any GET requests on a given endpoint
     * Expected Behavior:
     * 		> Restito should have captured GET request, and it should have captured only one GET request.
     * 		> Get the headers of the captured GET request 
     * 		  and make sure the headers match to the ones configured.
     * Finally:
     * 		> Stop the stub server started using restito.
     */

public void testGETRequestWithHeadersFromClient() {
		StubServer server = null;
		
		try {
		//This will start the stub server on 'PORT' and responds with HTTP 202 'ACCEPTED_202'
			TestUtil.restartRestitoServerForGETRequests(server, PORT2, ACCEPTED_202);
		
		RestClient.sendGETRequestWithCustomHeaders(PORT2);
		
		List<Call> callList = TestUtil.waitAndGetCallList(server, 30);
		assertTrue("GET request is not received from the RestClient. Test failed.", 
				(callList != null) && (callList.size() == 1));
		
		//Validate the headers of the GET request from REST Client
		Map<String, List<String>> headersFromRequest = callList.get(0).getHeaders();
		assertTrue("GET request contains header Accept and its value ",
				headersFromRequest.get("Accept").contains("text/html"));
		assertTrue("GET request contains header Authorization and its value ",
				headersFromRequest.get("Authorization").contains("Bearer 1234567890qwertyuiop"));
		assertTrue("GET request contains header Cache-Control and its value ",
				headersFromRequest.get("Cache-Control").contains("no-cache"));
		assertTrue("GET request contains header Connection and its value ",
				headersFromRequest.get("Connection").contains("keep-alive"));
		assertTrue("GET request contains header Content-Type and its value ",
				headersFromRequest.get("Content-Type").contains("application/json"));
		}
		catch(Exception e) {
			e.printStackTrace();
			fail("Test Failed due to exception : " + e);
		}
		finally {
			if(server != null) {
				server.stop();
            }
		}
	}
/**
     * Junit test to validate the POST request with body and headers from RestClient
     * Steps:
     * 		1) Create a stub server using Restito framework and configure it to listen on given port
     * 		2) Invoke the sendPOSTRequestWithJSONBody(..) method of RestClient
     * 		3) Restito captures the matching POST requests sent, if any.
     * 		4) Validate if Restito has captured any POST requests on given endpoint
     * Expected Behavior:
     * 		> Restito should have captured POST request and it should have captured only one POST request.
     * 		> Get the body of the captured POST request and validate the JSON values
     * Finally:
     * 		> Stop the stub server started using restito.
	 */

public void testPOSTRequestWithJSONBody() {
		StubServer server = null;
		
		try {
		//This will start the stub server on 'PORT' and responds with HTTP 202 'ACCEPTED_202'
			TestUtil.restartRestitoServerForPOSTRequests(server, PORT3, ACCEPTED_202);
		
		RestClient.sendPOSTRequestWithJSONBody(PORT3);
		
		List<Call> callList = TestUtil.waitAndGetCallList(server, 30);
		assertTrue("POST request is not received from the RestClient. Test failed.", 
				(callList != null) && (callList.size() == 1));
		
		//Validate the headers of the GET request from REST Client
		
		String requestBody = callList.get(0).getPostBody();
		JSONObject postRequestJSON = new JSONObject(requestBody);
		assertTrue("The timeUpdated in json is incorrect",
				postRequestJSON.get("timeUpdated").toString().equalsIgnoreCase("1535703838478"));
		assertTrue("The access_token in json is incorrect",
				postRequestJSON.get("access_token").toString().
				equalsIgnoreCase("abf8714d-73a3-42ab-9df8-d13fcb92a1d8"));
		assertTrue("The refresh_token in json is incorrect",
				postRequestJSON.get("refresh_token").toString().
				equalsIgnoreCase("d5a5ab08-c200-421d-ad46-2e89c2f566f5"));
		assertTrue("The token_type in json is incorrect",
				postRequestJSON.get("token_type").toString().equalsIgnoreCase("bearer"));
		assertTrue("The expires_in in json is incorrect",
				postRequestJSON.get("expires_in").toString().equalsIgnoreCase("1024"));
		assertTrue("The scope in json is incorrect",
				postRequestJSON.get("scope").toString().equalsIgnoreCase(""));
		}
		catch(Exception e) {
			e.printStackTrace();
			fail("Test Failed due to exception : " + e);
		}
		finally {
			if(server != null) {
				server.stop();
            }
		}
	}
}

========== CÓDIGO JAVA Termina ===========

Ventajas de utilizar Restito Framework para pruebas de clientes REST

Aquí hay ventajas y beneficios de Restito Framework para pruebas de clientes ReST.

  • No necesitamos que se desarrolle el servidor REST real para probar el Cliente REST.
  • Restito ofrece utilidades y métodos potentes y variados para simular diferentes comportamientos de un servidor. Por ejemplo: para probar cómo se comporta el cliente REST cuando el servidor responde con un error HTTP 404 o HTTP 503.
  • Los servidores Restito se pueden configurar en unos pocos milisegundos y se pueden finalizar una vez completadas las pruebas.
  • Restito admite todo tipo de contenidos de métodos HTTP como comprimidos, no comprimidos, unificados, aplicación/texto, aplicación/JSON, etc.

Desventajas de usar Restito Framework para pruebas de clientes REST

Aquí hay desventajas/desventajas de Restito Framework para pruebas de clientes ReST

  • La fuente del cliente REST debe modificarse para considerar "localhost" como una máquina servidor.
  • Abrir el servidor en cualquier puerto puede entrar en conflicto si utilizamos algún puerto de uso común como "8080" o "9443", etc.
  • Se recomienda utilizar puertos como 9092 o 9099, que no suelen utilizar otras herramientas.

Resumen

  • REST significa "Transferencia de estado representacional", que es una nueva forma estándar de comunicación entre dos sistemas en un momento determinado.
  • REST Client es un método o una herramienta para invocar una API de servicio REST que está expuesta a la comunicación por parte de cualquier sistema o proveedor de servicios.
  • En el método RestServer o una API que está expuesta para la comunicación por parte de cualquier sistema o proveedor de servicios.
  • Restito es una aplicación liviana que te ayuda a ejecutar cualquier tipo de solicitud HTTP
  • Cree un cliente HTTP y un método para enviar una solicitud HTTP GET a cualquier punto final del servidor
  • Inicie un servidor Restito para escuchar y capturar las solicitudes enviadas al punto final 'getevents'.
  • Inicie un servidor Restito para escuchar y capturar las solicitudes enviadas al punto final 'getevents' en localhost
  • Aquí, hemos implementado ejemplos para pruebas de automatización solo del Cliente REST.
  • No necesitamos que se desarrolle el servidor REST real para probar el Cliente REST.
  • La fuente del cliente REST debe modificarse para considerar "localhost" como una máquina servidor.