在上一篇文章中,我們探討了如何使用 SpringBootTest 進行端對端測試
今天,我們要介紹另一個強大的 API 測試工具:REST Assured
REST Assured
是一個專門用來測試 RESTful API
的 Java 函式庫,它提供了一種簡單、直觀的方式來驗證 HTTP 回應
使用 REST Assured 的基本步驟如下
given
: 設定測試的相關前置條件,例如請求參數、標頭等when
: 發送 HTTP 請求,執行實際的 API 呼叫then
: 驗證回應是否符合預期"一個簡單的例子,展示了 BDD 風格的測試
given()
.param("key", "value")
.when()
.get("/api/resource")
.then()
.statusCode(200)
.body("message", equalTo("Success"));
這種方式不僅使測試程式碼更容易閱讀和理解,還能夠清晰地描述測試的意圖和預期結果,這正是 BDD 的核心優勢
REST Assured 的強大之處不僅在於其流暢的 API
還在於它能夠與其他測試驗證工具無縫整合,特別是 Hamcrest
和 AssertJ
這種結合使得 API 測試變得更加靈活和表達力強
Hamcrest 是一個強大的 matcher 框架,它提供了一系列預定義的 matcher,可以用於構建靈活的驗證
REST Assured 原生支援 Hamcrest matcher,這使得驗證 API 回應變得非常直觀
.body("data.size()", equalTo(2))
.body("data.title", hasItems("測試待辦事項1", "測試待辦事項2"))
.body("data.find { it.completed == true }.title", equalTo("測試待辦事項2"))
這些驗證使用了 Hamcrest 的 equalTo(),hasItems() 等 matcher,可以輕鬆地驗證回應內容的各個方面
AssertJ 是另一個流行的驗證庫,它提供了一種更加流暢和易讀的方式來編寫驗證
雖然 REST Assured 主要使用 Hamcrest 進行回應驗證,但 AssertJ 在驗證從資料庫檢索的資料
或其他 Java 物件
時特別有用
assertThat(todoRepository.findAll())
.hasSize(2)
.extracting("title", "completed")
.containsExactly(
tuple("測試待辦事項1", false),
tuple("測試待辦事項2", true)
);
Hamcrest 和 AssertJ 都已經包含在 Spring Boot 的 spring-boot-starter-test
需要在 build.gradle
中添加 REST Assured
的依賴
testImplementation 'io.rest-assured:rest-assured:5.5.0'
接下來,讓我們開始改寫測試類別
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestPropertySource(locations = "classpath:application-test.properties")
public class TodoEndToEndTest {
@LocalServerPort
private int port;
@Autowired
private TodoRepository todoRepository;
@BeforeEach
void setUp() {
RestAssured.port = port;
todoRepository.deleteAll();
}
@Test
void createTodo() {
Todo newTodo = new Todo(null, "測試待辦事項", false);
// 呼叫 API
given()
.contentType(ContentType.JSON)
.body(newTodo)
.when()
.post("/api/todos")
.then()
.statusCode(200)
.body("success", equalTo(true))
.body("data.title", equalTo("測試待辦事項"))
.body("data.completed", equalTo(false));
// 驗證資料庫
assertThat(todoRepository.findAll()).hasSize(1);
}
@Test
void getAllTodos() {
// 新增測試資料
Todo todo1 = new Todo(null, "測試待辦事項1", false);
Todo todo2 = new Todo(null, "測試待辦事項2", true);
todoRepository.saveAll(Arrays.asList(todo1, todo2));
// 呼叫 API
given()
.when()
.get("/api/todos")
.then()
.statusCode(200)
.body("success", equalTo(true))
.body("data", hasSize(2))
.body("data[0].title", equalTo("測試待辦事項1"))
.body("data[0].completed", equalTo(false))
.body("data[1].title", equalTo("測試待辦事項2"))
.body("data[1].completed", equalTo(true));
}
@Test
void getTodo() {
// 新增測試資料
Todo todo = todoRepository.save(new Todo(null, "測試待辦事項", false));
// 呼叫 API
given()
.when()
.get("/api/todos/{id}", todo.getId())
.then()
.statusCode(200)
.body("success", equalTo(true))
.body("data.title", equalTo("測試待辦事項"))
.body("data.completed", equalTo(false));
}
@Test
void updateTodo() {
// 新增測試資料
Todo todo = todoRepository.save(new Todo(null, "原始待辦事項", false));
Todo updatedTodo = new Todo(todo.getId(), "更新後的待辦事項", true);
// 呼叫 API
given()
.contentType(ContentType.JSON)
.body(updatedTodo)
.when()
.put("/api/todos/{id}", todo.getId())
.then()
.statusCode(200);
// 驗證資料庫
Todo actualTodo = todoRepository.findById(todo.getId()).orElseThrow();
assertThat(actualTodo.getTitle()).isEqualTo("更新後的待辦事項");
assertThat(actualTodo.isCompleted()).isTrue();
}
@Test
void deleteTodo() {
// 新增測試資料
Todo savedTodo = todoRepository.save(new Todo(null, "要刪除的待辦事項", false));
// 呼叫 API
given()
.when()
.delete("/api/todos/{id}", savedTodo.getId())
.then()
.statusCode(200);
// 驗證資料庫
assertThat(todoRepository.findAll()).isEmpty();
}
}
這裡借用了SpringBootTest
來啟動測試用的應用程式,和使用 Repository
來新增和驗證資料
而 REST Assured
的重點在於,發送 HTTP 請求並驗證 API 的回應
我覺得比較麻煩的地方是,IDE 的排版設定,如果設定的不好,會讓整個測試類別的排版變得很醜,這點有點可惜
已經寫了一篇文章來介紹三種優雅的 JSON 驗證方法,有興趣的可以看看:Day 32.5 進化你的Spring Boot測試:三種優雅的JSON驗證方法
REST Assured 為 API 測試提供了一個強大而靈活的解決方案
它的流暢 API
使得編寫和閱讀測試變得更加容易
相比於 SpringBootTest,REST Assured 更專注於 API 層面的測試
,這使得它在某些情況下更適合進行端對端的 API 測試
透過結合 REST Assured 和 Spring Boot 測試框架,我們可以建立更全面、更靈活的 API 測試策略,從而提高應用程式的品質和可靠性
同步刊登於 Blog 「Spring Boot API 開發:從 0 到 1」Day 30 REST Assured 測試
我的粉絲專頁
圖片來源:AI 產生