Testowanie klienta REST za pomocą narzędzia Restito: Co to jest klient REST?

Co to jest ODPOCZYNEK?

REST oznacza „reprezentacyjny transfer stanu”, który jest nowym sposobem komunikacji pomiędzy dowolnymi dwoma systemami w danym momencie. Jeden z systemów nazywa się „Klientem REST”, a drugi „Serwerem REST”.

Zanim poznamy Restito Framework do testowania klientów REST, poznajmy najpierw kilka podstaw.

Co to jest klient REST?

Klient REST to metoda lub narzędzie umożliwiające wywołanie interfejsu API usługi REST, który jest udostępniany do komunikacji przez dowolnego dostawcę systemu lub usługi. Na przykład: jeśli interfejs API jest udostępniany w celu uzyskania w czasie rzeczywistym informacji o ruchu drogowym na trasie od Google, oprogramowanie/narzędzie wywołujące interfejs API ruchu Google nazywane jest klientem REST.

Co to jest serwer REST?

Jest to metoda lub interfejs API, który jest narażony na komunikację przez dowolnego dostawcę systemu lub usługi. Na przykład Google udostępnia interfejs API, aby uzyskać informacje o ruchu drogowym w czasie rzeczywistym na danej trasie.

W tym przypadku serwer Google musi być uruchomiony, aby odbierać żądania kierowane do odsłoniętego interfejsu API od różnych klientów.

Przykład:

Nadszedł czas na ustalenie pełnego, kompleksowego scenariusza na podstawie powyższych definicji.

Rozważmy aplikacje do rezerwacji taksówek, takie jak Uber, ponieważ firma potrzebuje informacji w czasie rzeczywistym o sytuacji na drogach na trasach, na których znajduje się dany pojazd.

Klient odpoczynku:

Klientem jest tutaj aplikacja mobilna Ubera, do której zalogował się kierowca. Ta aplikacja wysyła żądanie do interfejsu API REST udostępnianego przez mapy Google w celu uzyskania danych w czasie rzeczywistym. Na przykład żądanie HTTP GET.

Serwer odpoczynku:

W tym przykładzie Google jest dostawcą usługi, a interfejs API Map Google odpowiada wymaganymi szczegółami na żądanie aplikacji Uber.

Zarówno klient, jak i serwer są równie ważni w komunikacji REST.

Tutaj zaimplementowaliśmy przykłady testów automatycznych tylko klienta REST. Aby przetestować serwer REST, zobacz https://www.guru99.com/top-6-api-testing-tool.html.

Co to jest Restito?

Restito to framework opracowany przez Mkotsur. Jest to lekka aplikacja, która pomaga wykonywać dowolne żądania HTTP. Możesz używać Restito do testowania interfejsów API REST i wyszukiwania problemów w swojej aplikacji lub sieci.

Jak przetestować klienta REST za pomocą Restito?

Podzielmy ćwiczenie na następujące 4 kroki:

  1. Utwórz klienta HTTP i metodę wysyłania żądania HTTP GET do dowolnego punktu końcowego serwera. Na razie rozważ punkt końcowy jako http://localhost:9092/getevents.
  1. Uruchom serwer Restito, aby nasłuchiwać i przechwytywać żądania wysyłane do punktu końcowego „getevents” w localhost http://localhost:9092/getevents.
  1. Utwórz klasę testową, aby przetestować powyższego klienta. Wywołaj metodę klienta HTTP „sendGETRequest”, aby zainicjować żądanie GET do interfejsu API „getevents”.
  1. Zweryfikuj wywołanie HTTP GET przy użyciu frameworka Restito.

Przyjrzyjmy się szczegółowo każdemu z powyższych kroków.

Krok 1) Utwórz klienta HTTP i metodę wysyłania żądania HTTP GET do dowolnego punktu końcowego serwera.

========== Uruchamia się kod 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;
	}
}

========== KOD JAVA kończy się ===========

Krok 2) Uruchom serwer Restito, aby nasłuchiwać i przechwytywać żądania wysyłane do punktu końcowego „getevents” w localhost http://localhost:9092/getevents.

========== Uruchamia się kod 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();
    }


}

========== KOD JAVA kończy się ===========

Krok 3) Utwórz klasę testową, aby przetestować powyższego klienta. Wywołaj metodę sendGETRequest klienta HTTP, aby zainicjować żądanie GET do interfejsu API „getevents”.

========== Uruchamia się kod 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();
            }
		}	
	}

========== KOD JAVA kończy się ===========

Krok 4) Jak sprawdzić poprawność żądania GET z nagłówkami i żądania POST z treścią przy użyciu frameworka Restito.

========== Uruchamia się kod 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();
            }
		}
	}
}

========== KOD JAVA kończy się ===========

Zalety korzystania z Restito Framework do testowania klientów REST

Oto zalety/zalety Restito Framework do testowania klientów ReST

  • Do testowania klienta REST nie potrzebujemy tworzenia rzeczywistego serwera REST.
  • Restito zapewnia silne i zróżnicowane narzędzia i metody do symulowania różnych zachowań serwera. Na przykład: Aby przetestować, jak zachowuje się klient REST, gdy serwer odpowiada błędem HTTP 404 lub HTTP 503.
  • Serwery Restito można skonfigurować w ciągu kilku milisekund i można je zakończyć po zakończeniu testów.
  • Restito obsługuje wszystkie typy zawartości metod HTTP, takie jak skompresowana, nieskompresowana, ujednolicona, aplikacja/tekst, aplikacja/JSON itp.

Wady korzystania z Restito Framework do testowania klientów REST

Oto wady/wady Restito Framework do testowania klientów ReST

  • Należy zmodyfikować źródło klienta REST, aby traktować „localhost” jako serwer.
  • Otwarcie serwera na dowolnym porcie może powodować konflikt, jeśli użyjemy powszechnie używanego portu, takiego jak „8080” lub „9443” itp.
  • Zaleca się używanie portów takich jak 9092 lub 9099, które nie są powszechnie używane przez inne narzędzia.

Podsumowanie

  • REST oznacza „REpresentational State Transfer”, czyli nowy standardowy sposób komunikacji pomiędzy dowolnymi dwoma systemami w danym momencie.
  • Klient REST to metoda lub narzędzie umożliwiające wywołanie interfejsu API usługi REST, który jest narażony na komunikację przez dowolny system lub dostawcę usług.
  • W metodzie RestServer lub interfejsie API udostępnianym do komunikacji przez dowolny system lub dostawcę usług.
  • Restito to lekka aplikacja, która pomoże Ci wykonać dowolne żądanie HTTP
  • Utwórz klienta HTTP i metodę wysyłania żądania HTTP GET do dowolnego punktu końcowego serwera
  • Uruchom serwer Restito, aby nasłuchiwać i przechwytywać żądania wysyłane do punktu końcowego „getevents”.
  • Uruchom serwer Restito, aby nasłuchiwać i przechwytywać żądania wysyłane do punktu końcowego „getevents” w localhost
  • Tutaj zaimplementowaliśmy przykłady testów automatycznych tylko klienta REST.
  • Do testowania klienta REST nie potrzebujemy tworzenia rzeczywistego serwera REST.
  • Należy zmodyfikować źródło klienta REST, aby traktować „localhost” jako serwer.