Testování klienta REST pomocí nástroje Restito Tool: Co je klient Rest?

Co je REST?

REST je zkratka pro „REpresentational State Transfer“, což je nový způsob komunikace mezi libovolnými dvěma systémy v daném okamžiku. Jeden ze systémů se nazývá 'REST Client' a druhý se nazývá 'REST Server'.

Než se seznámíme s Restito Frameworkem pro testování klientů REST, naučíme se nejprve několik základů.

Co je REST Client?

Klient REST je metoda nebo nástroj pro vyvolání rozhraní API služby REST, které je vystaveno pro komunikaci jakýmkoli systémem nebo poskytovatelem služeb. Například: pokud je rozhraní API vystaveno za účelem získání dopravních informací o trase v reálném čase od společnosti Google, software/nástroj, který vyvolá rozhraní API pro provoz Google, se nazývá klient REST.

Co je REST Server?

Je to metoda nebo rozhraní API, které je vystaveno komunikaci jakéhokoli systému nebo poskytovatele služeb. Google například zpřístupňuje rozhraní API pro získávání dopravních informací na dané trase v reálném čase.

Zde musí být server Google v provozu, aby naslouchal všem požadavkům na vystavené rozhraní API od různých klientů.

Příklad:

Je čas vytvořit kompletní scénář End-to-End z výše uvedených definic.

Uvažujme aplikace pro rezervaci taxi jako Uber, protože společnost potřebuje informace v reálném čase o dopravní situaci na trasách, na kterých se dané vozidlo nachází.

Zbývající klient:

Zde je klientem mobilní aplikace Uber, ke které se řidič přihlásil. Tato aplikace odešle požadavek do REST API vystaveného mapami Google, aby získala data v reálném čase. Například požadavek HTTP GET.

Odpočinkový server:

V tomto příkladu je poskytovatelem služeb Google a API Google maps odpoví požadovanými podrobnostmi na požadavek aplikace Uber.

Klient i server jsou v REST komunikaci stejně důležité.

Zde jsme implementovali příklady pro testování automatizace pouze klienta REST. Pro testování REST serveru viz https://www.guru99.com/top-6-api-testing-tool.html.

Co je Restito?

Restito je framework vyvinutý společností Mkotsur. Je to lehká aplikace, která vám pomůže provést jakýkoli druh požadavku HTTP. Restito můžete použít k testování vašich REST API a k vyhledávání problémů ve vaší aplikaci nebo síti.

Jak otestovat klienta REST pomocí Restito?

Rozdělme cvičení do následujících 4 kroků:

  1. Vytvořte klienta HTTP a metodu pro odeslání požadavku HTTP GET na libovolný koncový bod serveru. Prozatím považujte koncový bod za http://localhost:9092/getevents.
  1. Spusťte server Restito, aby naslouchal a zachycoval požadavky odeslané do koncového bodu „getevents“ v localhost http://localhost:9092/getevents.
  1. Vytvořte testovací třídu pro testování výše uvedeného klienta. Vyvoláním metody 'sendGETRequest' klienta HTTP inicializujete požadavek GET na API 'getevents'.
  1. Ověřte volání HTTP GET pomocí frameworku Restito.

Pojďme se hlouběji ponořit do každého z výše uvedených kroků.

Krok 1) Vytvořte klienta HTTP a metodu pro odeslání požadavku HTTP GET na libovolný koncový bod serveru.

========== Spuštění kódu 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;
	}
}

========== KÓD JAVA Končí ===========

Krok 2) Spusťte server Restito, aby naslouchal a zachycoval požadavky odeslané do koncového bodu „getevents“ v localhost http://localhost:9092/getevents.

========== Spuštění kódu 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();
    }


}

========== KÓD JAVA Končí ===========

Krok 3) Vytvořte testovací třídu pro testování výše uvedeného klienta. Vyvoláním metody sendGETRequest HTTP klienta inicializujete požadavek GET na API 'getevents'.

========== Spuštění kódu 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();
            }
		}	
	}

========== KÓD JAVA Končí ===========

Krok 4) Jak ověřit požadavek GET pomocí záhlaví a požadavku POST s tělem pomocí rámce Restito.

========== Spuštění kódu 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();
            }
		}
	}
}

========== KÓD JAVA Končí ===========

Výhody použití Restito Framework pro testování klientů REST

Zde jsou výhody/výhody Restito Framework pro testování klientů ReST

  • K testování klienta REST nepotřebujeme vyvíjet skutečný server REST.
  • Restito poskytuje silné a rozmanité nástroje a metody pro zesměšňování různého chování serveru. Například: Chcete-li otestovat, jak se klient REST chová, když server odpoví chybou HTTP 404 nebo HTTP 503.
  • Servery Restito lze nastavit během několika milisekund a lze je po dokončení testů ukončit.
  • Restito podporuje všechny typy obsahu metod HTTP, jako je komprimovaný, nekomprimovaný, unifikovaný, aplikace/text, aplikace/JSON atd.

Nevýhody použití Restito Framework pro testování klientů REST

Zde jsou nevýhody/nevýhody Restito Framework pro testování klienta ReST

  • Zdroj klienta REST by měl být vyladěn tak, aby považoval „localhost“ za serverový stroj.
  • Otevření serveru v jakémkoli portu může být v konfliktu, pokud použijeme nějaký běžně používaný port, jako je „8080“ nebo „9443“ atd.
  • Doporučuje se používat porty jako 9092 nebo 9099, které jiné nástroje běžně nepoužívají.

Shrnutí

  • REST je zkratka pro „REpresentational State Transfer“, což je nový standardní způsob komunikace mezi libovolnými dvěma systémy v daném okamžiku.
  • Klient REST je metoda nebo nástroj pro vyvolání rozhraní API služby REST, které je vystaveno komunikaci jakéhokoli systému nebo poskytovatele služeb.
  • V metodě RestServer nebo API, které je vystaveno pro komunikaci jakýmkoli systémem nebo poskytovatelem služeb.
  • Restito je lehká aplikace, která vám pomůže provést jakýkoli druh požadavku HTTP
  • Vytvořte klienta HTTP a metodu pro odeslání požadavku HTTP GET na libovolný koncový bod serveru
  • Spusťte server Restito, aby naslouchal a zachycoval požadavky odeslané do koncového bodu „getevents“.
  • Spusťte server Restito, aby naslouchal a zachycoval požadavky odeslané do koncového bodu „getevents“ v localhost
  • Zde jsme implementovali příklady pro testování automatizace pouze klienta REST.
  • K testování klienta REST nepotřebujeme vyvíjet skutečný server REST.
  • Zdroj klienta REST by měl být vyladěn tak, aby považoval „localhost“ za serverový stroj.