1. 概述
在本文中,我們將介紹 Karate,一個用於 Java 的行為驅動開發 (BDD) 測試框架。
2. Karate 和 BDD
Karate 是 基於 Cucumber 的,另一個 BDD 測試框架,並共享一些相同的概念。其中之一是 使用 Gherkin 文件,該文件描述了被測試的功能。但是,與 Cucumber 不同,測試用例不使用 Java 編寫,並且完全由 Gherkin 文件描述。
Gherkin 文件以 ".feature" 擴展名保存。它以 Feature 關鍵字開頭,並在同一行中包含功能名稱。它還包含不同的測試場景,每個場景以 Scenario 關鍵字開頭,並由多個步驟組成,這些步驟使用 Given、When、Then、And 和 But 關鍵字。
關於 Cucumber 和 Gherkin 結構,請參考此處。
3. Maven 依賴和配置
為了在 Maven 項目中使用 Karate,我們只需要添加 karate-junit4 依賴:
<dependency>
<groupId>com.intuit.karate</groupId>
<artifactId>karate-junit4</artifactId>
<version>1.3.1</version>
<scope>test</scope>
</dependency>
此外,為了使我們的 .feature 文件與 Junit 類在同一目錄下,我們需要將以下代碼添加到我們的 Maven <build> 部分:
<build>
<testResources>
<testResource>
<directory>src/test/java</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</testResource>
</testResources>
<plugins>
...
</plugins>
</build>
這是 Karate 團隊推薦的做法,以保持測試和執行描述並存,並將 .feature 文件與其他測試資源分開。
4. 創建測試
我們將從編寫一些常見場景的測試,這些場景包含在 Gherkin
4.1. 測試狀態碼
讓我們編寫一個測試 GET 端點並檢查它是否返回
Scenario: Testing valid GET endpoint
Given url 'http://localhost:8097/user/get'
When method GET
Then status 200
這當然適用於所有可能的 HTTP 狀態碼。
4.2. 測試響應
讓我們編寫另一個場景,該場景測試 REST 端點返回特定響應:
Scenario: Testing the exact response of a GET endpoint
Given url 'http://localhost:8097/user/get'
When method GET
Then status 200
And match $ == {id:"1234",name:"John Smith"}
我們還可以專門檢查
And match $.id == "1234"
Scenario: Testing that GET response contains specific field
Given url 'http://localhost:8097/user/get'
When method GET
Then status 200
And match $ contains {id:"1234"}
4.3. 使用標記驗證響應值
在我們不知道返回的確切值的情況下,我們仍然可以使用
例如,我們可以使用標記來指示我們是否期望值為
#null #notnull
或者,我們可以使用標記來匹配字段中的特定類型的值:
#boolean #number #string
其他標記可用,用於當我們需要檢查字段是否包含 JSON 對象或數組時:
#array #object
還有標記用於匹配特定格式或正則表達式,以及評估布爾表達式的標記:
#uuid — value conforms to the UUID format#regex STR — value matches the regular expressionSTR #? EXPR — asserts that the JavaScript expressionEXPR evaluates totrue
最後,如果我們要對字段執行任何檢查,我們可以使用
讓我們重寫上述場景,以檢查
Scenario: Test GET request exact response
Given url 'http://localhost:8097/user/get'
When method GET
Then status 200
And match $ == {id:"#notnull",name:"John Smith"}
4.4. 測試帶有請求正文的 POST 端點
讓我們看一下測試 POST 端點並接受請求正文的最後一個場景:
Scenario: Testing a POST endpoint with request body
Given url 'http://localhost:8097/user/create'
And request { id: '1234' , name: 'John Smith'}
When method POST
Then status 200
And match $ contains {id:"#notnull"}
5. 運行測試
現在測試場景已完成,我們可以通過將 Karate 與 JUnit 集成來運行測試。@RunWith(Karate.class)
public class KarateUnitTest {
//...
}
為了演示 REST API,我們將使用 WireMock 服務器。
對於此示例,我們將模擬所有在 @BeforeClass 註解的方法中測試的端點。我們將關閉 WireMock 服務器,在 @AfterClass 註解的方法中:
private static WireMockServer wireMockServer
= new WireMockServer(WireMockConfiguration.options().port(8097));
@BeforeClass
public static void setUp() throws Exception {
wireMockServer.start();
configureFor("localhost", 8097);
stubFor(
get(urlEqualTo("/user/get"))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/json")
.withBody("{ \"id\": \"1234\", name: \"John Smith\" }")));
stubFor(
post(urlEqualTo("/user/create"))
.withHeader("content-type", equalTo("application/json"))
.withRequestBody(containing("id"))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/json; charset=UTF-8")
.withBody("{ \"id\": \"1234\", name: \"John Smith\" }")));
}
@AfterClass
public static void tearDown() throws Exception {
wireMockServer.stop();
}
當我們運行 KarateUnitTest 類時,WireMock 服務器創建 REST 端點,並運行指定功能文件中所有場景。
6. 結論
在本教程中,我們探討了如何使用 Karate 測試框架測試 REST API。