23 tháng 12 năm 2023 Công nghệ thông tin
REST Assured là một thư viện Java dùng để kiểm thử API RESTful. Nó cung cấp DSL (Ngôn ngữ cụ thể dành cho miền) đơn giản và trực quan để viết các trường hợp kiểm thử. REST Assured hỗ trợ các phương thức HTTP phổ biến như GET, POST, PUT, DELETE, PATCH, OPTIONS, và dễ dàng tích hợp với các khung kiểm thử nổi tiếng như TestNG, JUnit, Cucumber.
Bài viết này sẽ sử dụng “GitHub REST API” làm ví dụ minh họa cách sử dụng REST Assured.
Dưới đây là phiên bản JDK, Maven, REST Assured và JUnit được sử dụng tại thời điểm viết bài:
JDK: Amazon Corretto 17.0.8
Maven: 3.9.2
REST Assured: 5.4.0
JUnit: 5.10.1
1. Cấu trúc cú pháp của REST Assured
REST Assured sử dụng cú pháp tương tự Gherkin để viết các trường hợp kiểm thử. Chủ yếu có ba phần:
- Given (Giả sử): Giả định một kịch bản kiểm thử Phần này thường chuẩn bị công việc trước khi kiểm thử API, chẳng hạn như thiết lập Base URL, tiêu đề yêu cầu, tham số yêu cầu, v.v.
- When (Khi): Khi thực hiện một hành động nào đó Phần này sẽ thực thi yêu cầu và nhận phản hồi.
- Then (Thì): Thì kết quả mong đợi là gì? Kiểm tra xem phản hồi thực tế có khớp với phản hồi mong đợi không (ví dụ: mã trạng thái HTTP, nội dung phản hồi, tiêu đề phản hồi, v.v.).
Hiểu được cấu trúc cú pháp của REST Assured, bạn có thể bắt đầu sử dụng nó.
2. Chuẩn bị trước khi sử dụng
Ví dụ về dự án trong bài viết này sử dụng Maven quản lý. Trước khi bắt đầu, cần thêm phụ thuộc REST Assured và JUnit vào tệp pom.xml
ở gốc dự án:
<!-- pom.xml -->
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>5.4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.10.1</version>
<scope>test</scope>
</dependency>
Sau khi thêm phụ thuộc, bạn có thể bắt đầu sử dụng REST Assured.
3. Trải nghiệm ban đầu với REST Assured
Dưới đây là ví dụ về cách lấy danh sách nhánh của kho lưu trữ GitHub bằng REST Assured.
Câu lệnh CURL và kết quả phản hồi để lấy danh sách m88vin - cổng game quốc tế nhánh kho lưu trữ GitHub:
curl -L \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-GitHub-Api-Version: 2022-11-28" \
[
{
"name": "main",
"commit": {
"sha": "b67608b1c12198caf78448c239f11bd39e9953cf",
"url": "
},
"protected": false
}
]
Thử viết trường hợp kiểm thử cho giao diện này bằng REST Assured:
// src/test/java/com/example/tests/GitHubBranchAPITest.java
package com.example.tests;
import io.restassured.http.ContentType;
import org.junit.jupiter.api.Test;
import static io.restassured.RestAssured.baseURI;
import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.hasEntry;
import static org.hamcrest.Matchers.hasItem;
public class GitHubBranchAPITest {
@Test
public void listBranches() {
baseURI = "https://api.github.com";
given()
.auth().oauth2("ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
.header("X-GitHub-Api-Version", "2022-11-28")
.queryParam("page", 1)
.queryParam("per_page", 10)
.when()
.get("/branches")
.then()
.statusCode(200) // Kiểm tra mã trạng thái là 200
.body("$", hasItem(hasEntry("name", "main"))); // Kiểm tra mảng phản hồi chứa {"name": "main"}
}
}
Như bạn thấy, đoạn mã kiểm thử trên tuân theo cấu trúc ba phần điển hình của REST Assured: Given chuẩn bị các thông số yêu cầu, When thực thi yêu cầu, và Then thực hiện kiểm tra kết quả.
Tiếp tục phân tích đoạn mã trên:
baseURI
: URI cơ sở toàn cục của REST Assured. Sau khi đặt, không cần chỉ định đường dẫn đầy đủ mỗi lần gửi yêu cầu.accept()
: Định dạng dữ liệu chấp nhận, ví dụapplication/json
.header()
: Thiết lập tiêu đề yêu cầu, ví dụAuthorization
vàX-GitHub-Api-Version
.queryParam()
: Thiết lập tham số truy vấn URL.get()
: Phương thức yêu cầu, ví dụGET
. Các phương thức khác bao gồmPOST
,PUT
,PATCH
,DELETE
, v.v.statusCode()
: Kiểm tra mã trạng thái phản hồi.body()
: Kiểm tra nội dung phản hồi.
REST Assured hỗ trợ cú pháp dòng chảy để thiết lập các thông số, gửi yêu cầu và kiểm tra kết quả, giúp mã nguồn dễ hiểu hơn.
Nếu muốn gửi yêu cầu POST với dữ liệu dạng FORM (ContentType: application/x-www-form-urlencoded
), chỉ cần thay đổi phương thức tương ứng:
given()
.accept(ContentType.JSON)
.contentType(ContentType.URLENC) // application/x-www-form-urlencoded
.formParam("username", username)
.formParam("password", password)
.when()
.post("/login-form")
.then()
.statusCode(200);
4. Nâng cao việc sử dụng REST Assured
4.1. Phương pháp trích xuất giá trị từ phản hồi
Để trích xuất giá trị từ cấu trúc JSON cây, REST Assured cung cấp cách tiếp cận rất tiện lợi, chỉ cần đi qua từng lớp (ví dụ: grandparent.parent.child.grandson
).
Với ví dụ lấy thông tin chi tiết của một nhánh GitHub:
Câu lệnh CURL và kết quả phản hồi:
curl -L \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" [game nhà cái tặng tiền cược miễn phí](/post/how-to-use-github-auth-in-flask/) \
-H "X-GitHub-Api-Version: 2022-11-28" \
{
"name": "main",
"_links": {
"html": "
},
"protection": {
"enabled": false
},
...
}
Để trích xuất _links.html
và protection.enabled
từ phản hồi và thực hiện kiểm tra, có thể sử dụng phương pháp path()
của đối tượng Response
:
// src/test/java/com/example/tests/GitHubBranchAPITest.java#getBranch
Response response = given()
.pathParam("branch", "main")
.when()
.get("/branches/{branch}")
.then()
.statusCode(200)
.extract()
.response();
// Trích xuất trường
String link = response.path("_links.html");
Boolean protectionEnabled = response.path("protection.enabled");
// Kiểm tra
assertThat(link, equalTo("
Cũng có thể sử dụng đối tượng JsonPath
để trích xuất và kiểm tra:
// src/test/java/com/example/tests/GitHubBranchAPITest.java#getBranchUsingJsonPath
String responseBody = given()
.pathParam("branch", "main")
.when()
.get("/branches/{branch}")
.then()
.statusCode(200)
.extract()
.asString();
// Trích xuất trường
JsonPath jsonPath = from(responseBody);
String link = jsonPath.getString("_links.html");
Boolean protectionEnabled = jsonPath.getBoolean("protection.enabled");
// Kiểm tra
assertThat(link, equalTo("
Ngoài ra, có thể chuyển đổi phản hồi thành đối tượng Java đã định nghĩa.
Để sử dụng tính năng chuyển đổi, cần thêm phụ thuộc jackson-databind
vào pom.xml
:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.16.0</version>
<scope>test</scope>
</dependency>
Sau đó, định nghĩa lớp Java BranchEntity
:
// src/test/java/com/example/tests/model/BranchEntity.java
package com.example.tests.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
@JsonIgnoreProperties(ignoreUnknown=true)
public class BranchEntity {
private String name;
@JsonProperty("_links")
private Links links;
private Protection protection;
@JsonIgnoreProperties(ignoreUnknown=true)
public static class Links {
private String html;
}
@JsonIgnoreProperties(ignoreUnknown=true)
public static class Protection {
private Boolean enabled;
}
}
Chuyển đổi phản hồi thành đối tượng BranchEntity
và kiểm tra:
// src/test/java/com/example/tests/GitHubBranchAPITest.java#getBranchUsingDeserialization
BranchEntity branchEntity = given()
.pathParam("branch", "main")
.when()
.get("/branches/{branch}")
.then()
.statusCode(200)
.extract()
.as(BranchEntity.class);
// Kiểm tra
assertThat(branchEntity.getLinks().getHtml(), equalTo("
4.2. Ghi nhật ký yêu cầu hoặc phản hồi
Nhật ký rất hữu ích khi phát triển yêu cầu hoặc viết câu lệnh kiểm tra.
Để in nhật ký yêu cầu hoặc phản hồi, sử dụng ví dụ sau:
// src/test/java/com/example/tests/GitHubBranchAPITest.java#getBranchWithLog
given()
.log().all() // In tất cả chi tiết yêu cầu
.pathParam("branch", "main")
.when()
.get("/branches/{branch}")
.then()
.log().body() // In chỉ nội dung phản hồi
.statusCode(200)
.body("_links.html", equalTo("
Trên đây, yêu cầu in tất cả thông tin yêu cầu (bao gồm phương thức, URI, tham số, tiêu đề) và chỉ nội dung phản hồi.
Để chỉ in nhật ký khi kiểm tra thất bại, sử dụng:
// src/test/java/com/example/tests/GitHubBranchAPITest.java#getBranchWithLogOnWhenValidationFails
RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
given()
.pathParam("branch", "main")
.when()
.get("/branches/{branch}")
.then()
.statusCode(200)
.body("_links.html", equalTo("
4.3. Lọc và xử lý tập hợp trong phản hồi
REST Assured hỗ trợ lọc và xử lý tập hợp với cú pháp kiểu Groovy (hỗ trợ find, findAll, sum, max, min, v.v.).
Với ví Nạp Tiền Nohu71 dụ lấy danh sách cam kết từ kho GitHub:
Câu lệnh CURL và kết quả phản hồi:
curl -L \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-GitHub-Api-Version: 2022-11-28" \
[
{
"commit": {
"committer": {
"name": "Larry Yan",
"email": "someone@somedomain.com",
"date": "2023-12-22T06:39:38Z"
},
"message": "rest assured demo"
}
},
{
"commit": {
"committer": {
"name": "LeiLei Yan",
"email": "someone@somedomain.com",
"date": "2023-12-06T02:32:18Z"
},
"message": "builder pattern demo"
}
},
...
]
Để lọc cam kết theo email người cam kết và kiểm tra rằng có ít nhất một cam kết với thông điệp rest assured demo
, sử dụng:
// src/test/java/com/example/tests/GitHubCommitAPITest.java#filterCommits
.when()
.get("/commits")
.then()
.statusCode(200)
.body("findAll { it.commit.committer.email.equals('someone@somedomain.com') }.commit.message", hasItem("rest assured demo"));
Có thể sử dụng JsonPath
để lọc dữ liệu trước khi kiểm tra:
// src/test/java/com/example/tests/GitHubCommitAPITest.java#filterCommitsUsingJsonPath
Response response = get("/commits").then().extract().response();
List<String> commitMessages = from(response.asString()).getList("findAll { it.commit.committer.email.equals('someone@somedomain.com') }.commit.message");
// Kiểm tra
assertThat(response.statusCode(), equalTo(200));
assertThat(commitMessages, hasItem("rest assured demo"));
Để tìm cam kết gần nhất và kiểm tra thông điệp của nó:
// src/test/java/com/example/tests/GitHubCommitAPITest.java#latestCommit
.when()
.get("/commits")
.then()
.statusCode(200)
.body("max { it.commit.committer.date }.commit.message", equalTo("rest assured demo"));
4.4. Chuyển đổi phản hồi thành Collection
REST Assured hỗ trợ chuyển đổi mảng JSON thành Collection Java với TypeRef
.
Định nghĩa lớp CommitEntity
để ánh xạ phản hồi:
// src/test/java/com/example/tests/model/CommitEntity.java
package com.example.tests.model;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@JsonIgnoreProperties(ignoreUnknown=true)
public class CommitEntity {
private Commit commit;
@JsonIgnoreProperties(ignoreUnknown=true)
public static class Commit {
private Committer committer;
private String message;
}
@JsonIgnoreProperties(ignoreUnknown=true)
public static class Committer {
private String name;
private String email;
private String date;
}
}
Chuyển đổi phản hồi thành List<CommitEntity>
và kiểm tra:
// src/test/java/com/example/tests/GitHubCommitAPITest.java#deserializeCommits
List<CommitEntity> commits = get("/commits")
.then()
.statusCode(200)
.extract()
.as(new TypeRef<>() {});
// Kiểm tra
assertThat(commits, hasSize(10));
assertThat(commits.get(0).getCommit().getMessage(), equalTo("rest assured demo"));
4.5. Xây dựng dữ liệu yêu cầu
Để xây dựng dữ liệu yêu cầu, có thể sử dụng các kiểu dữ liệu gốc của Java như Map
, List
, REST Assured sẽ tự động chuyển đổi chúng sang JSON.
Với ví dụ tạo Issue trên GitHub:
Câu lệnh CURL:
curl -L \
-X POST \
-H "Accept: application/vnd.github+json" \
-H "Authorization: Bearer ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "X-GitHub-Api-Version: 2022-11-28" \
\
-d '{"title":"GitHub REST API Test","body":"Trying to raise a issue using REST API","assignees":["olzhy"],"labels":["bug"]}'
Mã kiểm thử tương ứng:
// src/test/java/com/example/tests/GitHubIssueAPITest.java#createIssue
Map<String, Object> requestBody = new HashMap<>();
requestBody.put("title", "GitHub REST API Test");
requestBody.put("body", "Trying to raise a issue using REST API");
requestBody.put("assignees", List.of("olzhy"));
requestBody.put("labels", List.of("bug"));
given()
.accept(ContentType.JSON)
.contentType(ContentType.JSON)
.body(requestBody)
.when()
.post("/issues")
.then()
.statusCode(201)
.body("title", equalTo("GitHub REST API Test"));
Như vậy, bài viết đã minh họa cách sử dụng REST Assured thông qua các ví dụ về GitHub REST API. Toàn bộ mã nguồn đã được đẩy lên GitHub cá nhân, mời theo dõi hoặc Fork.
[1] Automate API Testing With Java And Rest Assured | Medium - medium.com [2] REST Assured Getting Started | GitHub - github.com [3] REST Assured Usage | GitHub - github.com [4] GitHub REST API Endpoints | GitHub - github.com