REST-klienttesting med Restito-verktøyet: Hva er Rest Client?

Hva er REST?

REST står for "REpresentational State Transfer", som er en ny måte å kommunisere mellom to systemer på et gitt tidspunkt. Ett av systemene kalles 'REST Client', og det andre kalles 'REST Server'.

Før vi lærer om Restito Framework for REST-klienttesting, la oss først lære noen grunnleggende.

Hva er REST Client?

REST-klient er en metode eller et verktøy for å påkalle et REST-tjeneste-API som er eksponert for kommunikasjon av et hvilket som helst system eller tjenesteleverandør. For eksempel: hvis et API blir utsatt for å få sanntids trafikkinformasjon om en rute fra Google, kalles programvaren/verktøyet som påkaller Google Traffic API REST-klienten.

Hva er REST Server?

Det er en metode eller et API som er utsatt for kommunikasjon fra et hvilket som helst system eller tjenesteleverandør. For eksempel eksponerer Google et API for å få sanntids trafikkinformasjon på en gitt rute.

Her må Google-serveren være i gang for å lytte til eventuelle forespørsler til det eksponerte API-et fra forskjellige klienter.

Eksempel:

Det er på tide å etablere et fullstendig End-to-End-scenario fra definisjonene ovenfor.

La oss vurdere en taxibestillingsapplikasjon som Uber som et selskap trenger sanntidsinformasjon om trafikksituasjonen rundt rutene som et gitt kjøretøy befinner seg i.

Rest klient:

Her er klienten en Uber-mobilapplikasjon sjåføren har logget på. Denne appen sender en forespørsel til REST API eksponert av Google maps for å få sanntidsdata. For eksempel en HTTP GET-forespørsel.

Rest server:

I dette eksemplet er Google tjenesteleverandøren, og Google maps' API svarer med de nødvendige detaljene på Uber-appens forespørsel.

Både klienten og serveren er like viktige i REST-kommunikasjon.

Her har vi implementert eksempler for automatiseringstesting av kun REST-klienten. For testing av REST-server, se https://www.guru99.com/top-6-api-testing-tool.html.

Hva er Restito?

Restito er et rammeverk utviklet av Mkotsur. Det er en lett app som hjelper deg med å utføre alle typer HTTP-forespørsel. Du kan bruke Restito til å teste REST API-ene dine og til å søke etter problemer i applikasjonen eller nettverket ditt.

Hvordan teste REST-klient ved hjelp av Restito?

La oss dele øvelsen inn i følgende 4 trinn:

  1. Opprett en HTTP-klient og metode for å sende en HTTP GET-forespørsel til et hvilket som helst serverendepunkt. For nå, betrakt endepunktet som http://localhost:9092/getevents.
  1. Start en Restito-server for å lytte og fange opp forespørslene som sendes til endepunktet 'getevents' i localhost http://localhost:9092/getevents.
  1. Opprett en testklasse for å teste klienten ovenfor. Påkall HTTP-klienten 'sendGETRequest'-metoden for å starte en GET-forespørsel til API-en 'getevents'.
  1. Valider HTTP GET-kallet ved å bruke Restito-rammeverket.

La oss dykke dypt inn i hvert av trinnene ovenfor.

Trinn 1) Opprett en HTTP-klient og metode for å sende HTTP GET-forespørsel til et hvilket som helst serverendepunkt.

========== JAVA-KODE starter ============

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;
	}
}

========== JAVA-KODE slutter ============

Trinn 2) Start en Restito-server for å lytte og fange opp forespørslene som sendes til endepunktet 'getevents' i localhost http://localhost:9092/getevents.

========== JAVA-KODE starter ============

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();
    }


}

========== JAVA-KODE slutter ============

Trinn 3) Opprett en testklasse for å teste klienten ovenfor. Påkall HTTP-klienten sendGETRequest-metoden for å starte en GET-forespørsel til API 'getevents'.

========== JAVA-KODE starter ============
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();
            }
		}	
	}

========== JAVA-KODE slutter ============

Trinn 4) Hvordan validere GET-forespørsel med Headers og POST-forespørsel med kroppen ved å bruke Restito-rammeverket.

========== JAVA-KODE starter ============

/**
     * 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();
            }
		}
	}
}

========== JAVA-KODE slutter ============

Fordeler med å bruke Restito Framework for REST-klienttesting

Her er fordeler/fordeler med Restito Framework for ReST-klienttesting

  • Vi trenger ikke selve REST-serveren som skal utvikles for å teste REST-klienten.
  • Restito tilbyr sterke og varierte verktøy og metoder for å håne forskjellig oppførsel til en server. For eksempel: For å teste hvordan REST-klienten oppfører seg når serveren svarer med HTTP 404-feil eller HTTP 503-feil.
  • Restito-servere kan settes opp på få millisekunder og kan avsluttes etter at testene er fullført.
  • Restito støtter alle typer HTTP-metodeinnhold som komprimert, ikke-komprimert, enhetlig, applikasjon/tekst, applikasjon/JSON, etc.

Ulemper ved å bruke Restito Framework for REST-klienttesting

Her er ulemper/ulemper med Restito Framework for ReST-klienttesting

  • REST-klientkilden bør justeres for å vurdere 'localhost' som en servermaskin.
  • Å åpne server i en hvilken som helst port kan komme i konflikt hvis vi bruker en vanlig port som '8080' eller '9443' osv.
  • Det anbefales å bruke porter som 9092 eller 9099, som ikke brukes ofte av andre verktøy.

Oppsummering

  • REST står for "Representational State Transfer" som er en ny standard måte for kommunikasjon mellom to systemer på et gitt tidspunkt.
  • REST-klient er en metode eller et verktøy for å påkalle en REST-tjeneste-API som er utsatt for kommunikasjon fra et hvilket som helst system eller tjenesteleverandør.
  • In RestServer-metoden eller en API som er eksponert for kommunikasjon av et hvilket som helst system eller tjenesteleverandør.
  • Restito er en lettvektsapp som hjelper deg med å utføre alle typer HTTP-forespørsel
  • Opprett en HTTP-klient og metode for å sende en HTTP GET-forespørsel til et hvilket som helst serverendepunkt
  • Start en Restito-server for å lytte og fange opp forespørslene som sendes til endepunktet 'getevents'.
  • Start en Restito-server for å lytte og fange opp forespørslene som sendes til endepunktet 'getevents' i localhost
  • Her har vi implementert eksempler for automatiseringstesting av kun REST-klienten.
  • Vi trenger ikke selve REST-serveren som skal utvikles for å teste REST-klienten.
  • REST-klientkilden bør justeres for å vurdere 'localhost' som en servermaskin.