REST Client Test ved hjælp af Restito Tool: Hvad er Rest Client?

Hvad er REST?

REST står for "REpresentational State Transfer", som er en ny måde at kommunikere mellem to systemer på et givet tidspunkt. Et af systemerne hedder 'REST Client', og det andet hedder 'REST Server'.

Inden vi lærer om Restito Framework til REST-klienttestning, lad os først lære et par grundlæggende ting.

Hvad er REST Client?

REST-klient er en metode eller et værktøj til at påkalde en REST-service-API, der er eksponeret for kommunikation af ethvert system eller tjenesteudbyder. For eksempel: Hvis en API udsættes for at få trafikinformation i realtid om en rute fra Google, kaldes softwaren/værktøjet, der kalder Google Traffic API, REST-klienten.

Hvad er REST Server?

Det er en metode eller en API, der er udsat for kommunikation fra ethvert system eller tjenesteudbyder. For eksempel eksponerer Google en API for at få trafikinformation i realtid på en given rute.

Her skal Google-serveren være oppe at køre for at lytte til eventuelle anmodninger til den eksponerede API fra forskellige klienter.

Eksempel:

Det er på tide at etablere et komplet End-to-End-scenarie ud fra ovenstående definitioner.

Lad os overveje en taxabestillingsapplikation som Uber, da en virksomhed har brug for realtidsinformation om trafiksituationen omkring de ruter, som et givet køretøj befinder sig i.

Resten klient:

Her er klienten en Uber-mobilapplikation, chaufføren har logget på. Denne app sender en anmodning til REST-API'en, der er eksponeret af Google maps, for at få realtidsdata. For eksempel en HTTP GET-anmodning.

Rest server:

I dette eksempel er Google tjenesteudbyderen, og Google maps' API svarer med den påkrævede details til Uber-appens anmodning.

Både klienten og serveren er lige vigtige i REST-kommunikation.

Her har vi implementeret eksempler på automatiseringstest af kun REST Client. For test af REST-server, se https://www.guru99.com/top-6-api-testing-tool.html.

Hvad er Restito?

Restito er en rammek developred af Mkotsur. Det er en letvægtsapp, der hjælper dig med at udføre enhver form for HTTP-anmodning. Du kan bruge Restito til at teste dine REST API'er og til at søge efter problemer i din applikation eller dit netværk.

Hvordan tester man REST klient ved hjælp af Restito?

Lad os dele øvelsen op i folloenwing 4 trin:

  1. Opret en HTTP-klient og metode til at sende en HTTP GET-anmodning til ethvert serverendepunkt. Betragt nu, at slutpunktet er http://localhost:9092/getevents.
  1. Start en Restito-server for at lytte og fange anmodningerne sendt til slutpunktet 'getevents' i localhost http://localhost:9092/getevents.
  1. Opret en testklasse for at teste ovenstående klient. Kald HTTP-klienten 'sendGETRequest'-metoden for at starte en GET-anmodning til API'en 'getevents'.
  1. Valider HTTP GET-kaldet ved hjælp af Restito-rammeværket.

Lad os dykke dybt ned i hvert af ovenstående trin.

Trin 1) Opret en HTTP-klient og metode til at sende HTTP GET-anmodning til ethvert 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 ============

Trin 2) Start en Restito-server for at lytte og fange anmodningerne sendt til slutpunktet '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 ============

Trin 3) Opret en testklasse for at teste ovenstående klient. Kald HTTP-klienten sendGETRequest-metoden for at starte en GET-anmodning til API'et '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 ============

Trin 4) Hvordan man validerer GET-anmodning med Headers og POST-anmodning med kroppen ved hjælp af Restito-ramme.

========== 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 ============

Fordele ved at bruge Restito Framework til REST-klienttest

Her er fordele/fordele ved Restito Framework til ReST-klienttestning

  • Vi behøver ikke selve REST-serveren, der skal udvikles for at teste REST-klienten.
  • Restito giver strong og forskellige værktøjer og metoder til at håne forskellige opførsel af en server. For eksempel: For at teste, hvordan REST-klienten opfører sig, når serveren svarer med HTTP 404-fejl eller HTTP 503-fejl.
  • Restito-servere kan konfigureres på få millisekunder og kan afsluttes, efter at testene er afsluttet.
  • Restito understøtter alle typer HTTP-metodeindhold som komprimeret, ikke-komprimeret, unified, applikation/tekst, applikation/JSON osv.

Ulemper ved at bruge Restito Framework til REST-klienttest

Her er ulemper/ulemper ved Restito Framework til ReST-klienttestning

  • REST-klientkilden bør justeres for at betragte 'localhost' som en servermaskine.
  • Åbning af server i enhver port kan være i konflikt, hvis vi bruger en almindeligt brugt port som '8080' eller '9443' osv.
  • Det anbefales at bruge porte som 9092 eller 9099, som ikke almindeligvis bruges af andre værktøjer.

Resumé

  • REST står for "Representational State Transfer", som er en ny standard måde at kommunikere mellem to systemer på et givet tidspunkt.
  • REST Client er en metode eller et værktøj til at påkalde en REST service API, der er udsat for kommunikation fra ethvert system eller tjenesteudbyder.
  • In RestServer-metoden eller en API, der er eksponeret for kommunikation af ethvert system eller tjenesteudbyder.
  • Restito er en letvægtsapp, der hjælper dig med at udføre enhver form for HTTP-anmodning
  • Opret en HTTP-klient og metode til at sende en HTTP GET-anmodning til ethvert serverendepunkt
  • Start en Restito-server for at lytte og fange de anmodninger, der sendes til slutpunktet 'getevents'.
  • Start en Restito-server for at lytte og fange anmodningerne sendt til slutpunktet 'getevents' i localhost
  • Her har vi implementeret eksempler på automatiseringstest af kun REST Client.
  • Vi behøver ikke selve REST-serveren, der skal udvikles for at teste REST-klienten.
  • REST-klientkilden bør justeres for at betragte 'localhost' som en servermaskine.