การทดสอบไคลเอ็นต์ REST โดยใช้เครื่องมือ Restito: Rest Client คืออะไร
REST คืออะไร?
REST ย่อมาจาก “Representational State Transfer” ซึ่งเป็นวิธีการสื่อสารรูปแบบใหม่ระหว่างสองระบบ ณ เวลาที่กำหนด ระบบหนึ่งเรียกว่า 'REST Client' และอีกระบบหนึ่งเรียกว่า 'REST Server'
ก่อนที่จะเรียนรู้เกี่ยวกับ Restito Framework สำหรับการทดสอบไคลเอ็นต์ REST ให้เราเรียนรู้พื้นฐานบางประการก่อน
ไคลเอนต์ REST คืออะไร?
REST Client คือวิธีการหรือเครื่องมือในการเรียกใช้ API บริการ REST ที่เปิดเผยเพื่อการสื่อสารโดยระบบหรือผู้ให้บริการใดๆ ตัวอย่างเช่น หาก API ถูกเปิดเผยเพื่อรับข้อมูลการจราจรแบบเรียลไทม์เกี่ยวกับเส้นทางจาก Google ซอฟต์แวร์/เครื่องมือที่เรียกใช้ API การรับส่งข้อมูลของ Google จะเรียกว่าไคลเอนต์ REST
เซิร์ฟเวอร์ REST คืออะไร?
เป็นวิธีหรือ API ที่ถูกเปิดเผยต่อการสื่อสารโดยระบบหรือผู้ให้บริการใดๆ ตัวอย่างเช่น Google เปิดเผย API เพื่อรับข้อมูลการจราจรแบบเรียลไทม์บนเส้นทางที่กำหนด
ที่นี่ เซิร์ฟเวอร์ของ Google จะต้องเปิดใช้งานเพื่อรับฟังคำขอใดๆ ไปยัง API ที่เปิดเผยจากไคลเอนต์ที่แตกต่างกัน
ตัวอย่าง:
ถึงเวลาที่จะต้องสร้างสถานการณ์ตั้งแต่ต้นจนจบโดยสมบูรณ์จากคำจำกัดความข้างต้น
ให้เราพิจารณาแอปพลิเคชันจองรถแท็กซี่เช่น Uber เนื่องจากบริษัทต้องการข้อมูลเรียลไทม์เกี่ยวกับสถานการณ์การจราจรรอบเส้นทางที่มียานพาหนะนั้นๆ อยู่
ลูกค้าที่เหลือ:
ลูกค้าคือแอปพลิเคชัน Uber บนมือถือที่คนขับลงชื่อเข้าใช้ แอปนี้ส่งคำขอไปยัง REST API ที่ Google Maps เปิดเผยเพื่อรับข้อมูลแบบเรียลไทม์ ตัวอย่างเช่น คำขอ HTTP GET
เซิร์ฟเวอร์ที่เหลือ:
ในตัวอย่างนี้ Google คือผู้ให้บริการและ API ของ Google Maps ตอบสนองด้วยรายละเอียดที่จำเป็นต่อคำขอของแอป Uber
ทั้งไคลเอ็นต์และเซิร์ฟเวอร์มีความสำคัญเท่าเทียมกันในการสื่อสาร REST
ที่นี่ เราได้นำตัวอย่างสำหรับการทดสอบอัตโนมัติของไคลเอ็นต์ REST มาใช้งานเท่านั้น สำหรับการทดสอบเซิร์ฟเวอร์ REST โปรดดูที่ https://www.guru99.com/top-6-api-testing-tool.html.
เรสติโต้คืออะไร?
Restito เป็นเฟรมเวิร์กที่พัฒนาโดย Mkotsur เป็นแอปน้ำหนักเบาที่ช่วยให้คุณดำเนินการคำขอ HTTP ทุกประเภท คุณสามารถใช้ Restito เพื่อทดสอบ REST API และค้นหาปัญหาในแอปพลิเคชันหรือเครือข่ายของคุณ
จะทดสอบไคลเอนต์ REST โดยใช้ Restito ได้อย่างไร
เราจะแบ่งการออกกำลังกายออกเป็น 4 ขั้นตอนดังต่อไปนี้:
- สร้างไคลเอ็นต์ HTTP และวิธีการส่งคำขอ HTTP GET ไปยังจุดสิ้นสุดของเซิร์ฟเวอร์ ในตอนนี้ให้พิจารณาว่าจุดสิ้นสุดจะเป็น
http://localhost:9092/getevents
.
- เริ่มเซิร์ฟเวอร์ Restito เพื่อฟังและบันทึกคำขอที่ส่งไปยังจุดสิ้นสุด 'getevents' ใน localhost
http://localhost:9092/getevents
.
- สร้างคลาสทดสอบเพื่อทดสอบไคลเอนต์ข้างต้น เรียกใช้เมธอดไคลเอ็นต์ HTTP 'sendGETRequest' เพื่อเริ่มต้นคำขอ GET ไปยัง API 'getevents'
- ตรวจสอบการเรียก HTTP GET โดยใช้เฟรมเวิร์ก Restito
ให้เราดำดิ่งลงในแต่ละขั้นตอนข้างต้น
ขั้นตอน 1) สร้างไคลเอนต์ HTTP และวิธีการส่งคำขอ HTTP GET ไปยังจุดสิ้นสุดของเซิร์ฟเวอร์
========== รหัส 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; } }
========== รหัส JAVA สิ้นสุด ===========
ขั้นตอน 2) เริ่มเซิร์ฟเวอร์ Restito เพื่อฟังและบันทึกคำขอที่ส่งไปยังจุดสิ้นสุด 'getevents' ใน localhost http://localhost:9092/getevents
.
========== รหัส 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(); } }
========== รหัส JAVA สิ้นสุด ===========
ขั้นตอน 3) สร้างคลาสทดสอบเพื่อทดสอบไคลเอ็นต์ข้างต้น เรียกใช้เมธอด sendGETRequest ของไคลเอ็นต์ HTTP เพื่อเริ่มต้นคำขอ GET ไปยัง API 'getevents'
========== รหัส 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(); } } }
========== รหัส JAVA สิ้นสุด ===========
ขั้นตอน 4) วิธีตรวจสอบคำขอ GET ด้วยส่วนหัวและคำขอ POST กับเนื้อหาโดยใช้เฟรมเวิร์ก Restito
========== รหัส 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(); } } } }
========== รหัส JAVA สิ้นสุด ===========
ข้อดีของการใช้ Restito Framework สำหรับการทดสอบไคลเอนต์ REST
นี่คือข้อดี/ประโยชน์ของ Restito Framework สำหรับการทดสอบไคลเอ็นต์ ReST
- เราไม่จำเป็นต้องมีการพัฒนาเซิร์ฟเวอร์ REST จริงเพื่อทดสอบไคลเอนต์ REST
- Restito นำเสนอยูทิลิตี้และวิธีการที่แข็งแกร่งและหลากหลายเพื่อจำลองพฤติกรรมที่แตกต่างกันของเซิร์ฟเวอร์ ตัวอย่างเช่น: เพื่อทดสอบว่าไคลเอนต์ REST ทำงานอย่างไรเมื่อเซิร์ฟเวอร์ตอบสนองด้วยข้อผิดพลาด HTTP 404 หรือข้อผิดพลาด HTTP 503
- เซิร์ฟเวอร์ Restito สามารถตั้งค่าได้ภายในเวลาไม่กี่มิลลิวินาทีและสามารถยุติการทำงานได้หลังจากการทดสอบเสร็จสิ้น
- Restito รองรับเนื้อหาวิธี HTTP ทุกประเภท เช่น บีบอัด ไม่บีบอัด รวมเป็นหนึ่ง แอปพลิเคชัน/ข้อความ แอปพลิเคชัน/JSON ฯลฯ
ข้อเสียของการใช้ Restito Framework สำหรับการทดสอบไคลเอ็นต์ REST
นี่คือข้อเสีย/ข้อเสียของ Restito Framework สำหรับการทดสอบไคลเอ็นต์ ReST
- แหล่งที่มาของไคลเอ็นต์ REST ควรได้รับการปรับแต่งเพื่อพิจารณา 'localhost' เป็นเครื่องเซิร์ฟเวอร์
- การเปิดเซิร์ฟเวอร์ในพอร์ตใดๆ อาจขัดแย้งกันหากเราใช้พอร์ตที่ใช้กันทั่วไปเช่น '8080' หรือ '9443' เป็นต้น
- ขอแนะนำให้ใช้พอร์ตเช่น 9092 หรือ 9099 ซึ่งเครื่องมืออื่นๆ ไม่ค่อยได้ใช้
สรุป
- REST ย่อมาจาก "Representational State Transfer" ซึ่งเป็นวิธีมาตรฐานใหม่ในการสื่อสารระหว่างสองระบบ ณ เวลาที่กำหนด
- REST Client คือวิธีการหรือเครื่องมือในการเรียกใช้ API บริการ REST ที่เปิดเผยต่อการสื่อสารโดยระบบหรือผู้ให้บริการใดๆ
- ในวิธี RestServer หรือ API ที่ถูกเปิดเผยเพื่อการสื่อสารโดยระบบหรือผู้ให้บริการใดๆ
- Restito เป็นแอปขนาดเล็กที่จะช่วยให้คุณดำเนินการคำขอ HTTP ได้ทุกประเภท
- สร้างไคลเอ็นต์ HTTP และวิธีการส่งคำขอ HTTP GET ไปยังจุดสิ้นสุดของเซิร์ฟเวอร์
- เริ่มเซิร์ฟเวอร์ Restito เพื่อฟังและบันทึกคำขอที่ส่งไปยังปลายทาง 'getevents'
- เริ่มเซิร์ฟเวอร์ Restito เพื่อฟังและบันทึกคำขอที่ส่งไปยังจุดสิ้นสุด 'getevents' ใน localhost
- ที่นี่ เราได้นำตัวอย่างสำหรับการทดสอบอัตโนมัติของไคลเอ็นต์ REST มาใช้งานเท่านั้น
- เราไม่จำเป็นต้องมีการพัฒนาเซิร์ฟเวอร์ REST จริงเพื่อทดสอบไคลเอนต์ REST
- แหล่งที่มาของไคลเอ็นต์ REST ควรได้รับการปรับแต่งเพื่อพิจารณา 'localhost' เป็นเครื่องเซิร์ฟเวอร์