REST Client Testing med Restito Tool: Vad är Rest Client?

Vad är REST?

REST står för "REpresentational State Transfer", vilket är ett nytt sätt att kommunicera mellan två system vid en given tidpunkt. Ett av systemen kallas 'REST Client' och det andra kallas 'REST Server'.

Innan vi lär oss om Restito Framework för REST-klienttestning, låt oss först lära oss några grunder.

Vad är REST Client?

REST Client är en metod eller ett verktyg för att anropa ett REST-tjänst-API som är exponerat för kommunikation av alla system eller tjänsteleverantörer. Till exempel: om ett API utsätts för att få trafikinformation i realtid om en rutt från Google, kallas programvaran/verktyget som anropar Googles trafik-API för REST-klienten.

Vad är REST Server?

Det är en metod eller ett API som utsätts för kommunikation från vilket system eller tjänsteleverantör som helst. Till exempel exponerar Google ett API för att få trafikinformation i realtid på en given rutt.

Här måste Googles server vara igång för att lyssna på eventuella förfrågningar till det exponerade API:et från olika klienter.

Exempelvis:

Det är dags att upprätta ett komplett end-to-end-scenario från ovanstående definitioner.

Låt oss betrakta en taxibokningsapplikation som Uber eftersom ett företag behöver realtidsinformation om trafiksituationen runt de rutter som ett givet fordon befinner sig i.

Vila klient:

Här är klienten en Uber-mobilapplikation som föraren har loggat in på. Denna app skickar en förfrågan till REST API som exponeras av Google maps för att få realtidsdata. Till exempel en HTTP GET-begäran.

Restserver:

I det här exemplet är Google tjänsteleverantören och Google maps API svarar med den nödvändiga informationen på Uber-appens begäran.

Både klienten och servern är lika viktiga i REST-kommunikation.

Här har vi implementerat exempel för automationstestning av endast REST-klienten. För att testa REST-servern, se https://www.guru99.com/api-testing-tool.html.

Vad är Restito?

Restito är ett ramverk utvecklat av Mkotsur. Det är en lättviktsapp som hjälper dig att utföra alla slags HTTP-förfrågningar. Du kan använda Restito för att testa dina REST API:er och för att söka efter problem i din applikation eller ditt nätverk.

Hur testar man REST-klienten med Restito?

Låt oss dela upp övningen i följande 4 steg:

  1. Skapa en HTTP-klient och metod för att skicka en HTTP GET-begäran till valfri serverslutpunkt. För nu, betrakta slutpunkten som http://localhost:9092/getevents.
  1. Starta en Restito-server för att lyssna och fånga de förfrågningar som skickas till slutpunkten 'getevents' i localhost http://localhost:9092/getevents.
  1. Skapa en testklass för att testa klienten ovan. Anropa HTTP-klienten 'sendGETRequest'-metoden för att initiera en GET-begäran till API:et 'getevents'.
  1. Validera HTTP GET-anropet med Restito-ramverket.

Låt oss djupdyka i vart och ett av stegen ovan.

Steg 1) Skapa en HTTP-klient och metod för att skicka HTTP GET-begäran till valfri serverslutpunkt.

========== JAVA-KOD startar ============

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

Steg 2) Starta en Restito-server för att lyssna och fånga de förfrågningar som skickas till slutpunkten 'getevents' i localhost http://localhost:9092/getevents.

========== JAVA-KOD startar ============

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

Steg 3) Skapa en testklass för att testa klienten ovan. Anropa HTTP-klienten sendGETRequest-metoden för att initiera en GET-begäran till API:et "getevents".

========== JAVA-KOD startar ============

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

Steg 4) Hur man validerar GET-begäran med Headers och POST-begäran med kroppen med hjälp av Restito-ramverket.

========== JAVA-KOD startar ============

/**
     * 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-KOD slutar ============

Fördelar med att använda Restito Framework för REST-klienttestning

Här är fördelar/fördelar med Restito Framework för ReST-klienttestning

  • Vi behöver inte själva REST-servern utvecklas för att testa REST-klienten.
  • Restito tillhandahåller starka och varierande verktyg och metoder för att håna olika beteenden hos en server. Till exempel: För att testa hur REST-klienten beter sig när servern svarar med HTTP 404-fel eller HTTP 503-fel.
  • Restito-servrar kan ställas in på några millisekunder och kan avslutas efter att testerna är klara.
  • Restito stöder alla typer av HTTP-metodinnehåll som komprimerat, icke-komprimerat, unified, application/text, application/JSON, etc.

Nackdelar med att använda Restito Framework för REST-klienttestning

Här är nackdelar/nackdelar med Restito Framework för ReST-klienttestning

  • REST-klientkällan bör justeras för att betrakta "localhost" som en servermaskin.
  • Att öppna servern i valfri port kan komma i konflikt om vi använder någon vanlig port som '8080' eller '9443' etc.
  • Det rekommenderas att använda portar som 9092 eller 9099, som inte vanligtvis används av andra verktyg.

Sammanfattning

  • REST står för "Representational State Transfer" vilket är ett nytt standardsätt för kommunikation mellan två system vid en given tidpunkt.
  • REST Client är en metod eller ett verktyg för att anropa ett REST-tjänst-API som utsätts för kommunikation från vilket system eller tjänsteleverantör som helst.
  • In RestServer-metoden eller ett API som är exponerat för kommunikation av alla system eller tjänsteleverantörer.
  • Restito är en lättviktsapp som hjälper dig att utföra alla typer av HTTP-förfrågningar
  • Skapa en HTTP-klient och metod för att skicka en HTTP GET-begäran till valfri serverslutpunkt
  • Starta en Restito-server för att lyssna och fånga de förfrågningar som skickas till slutpunkten 'getevents'.
  • Starta en Restito-server för att lyssna och fånga de förfrågningar som skickas till slutpunkten 'getevents' i localhost
  • Här har vi implementerat exempel för automationstestning av endast REST-klienten.
  • Vi behöver inte själva REST-servern utvecklas för att testa REST-klienten.
  • REST-klientkällan bör justeras för att betrakta "localhost" som en servermaskin.

Sammanfatta detta inlägg med: