1. 概述
在本教程中,我們將使用 RestAssured 庫向服務器發送多部分請求。 這對於測試 Spring 中的多部分控制器或針對已部署服務器進行集成測試非常有用。
2. 什麼是多部分請求?
多部分請求是一種 HTTP POST 請求。 它們允許在一個請求中發送各種文件或數據。
在多部分請求中,數據被分成多個部分。 每個部分都有一個名稱以及一組標頭,指示其包含的數據類型。 數據和每個部分之間的邊界都進行編碼。
3. 安裝配置
讓我們安裝並配置我們將會使用的庫。
3.1. RestAssured 測試庫
RestAssured 是一個基於 Java 的庫,它提供了一種特定於領域的語言,用於編寫 RESTful Web 服務自動化測試。
讓我們先將 RestAssured 庫添加到我們的 pom.xml 中:
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>5.5.0</version>
<scope>test</scope>
</dependency>3.2. 設置 Wiremock 服務器
我們將使用 RestAssured 發送多部分請求。在實際應用中,這些請求將到達我們想要測試的目標服務器。為了便於我們的示例,我們將用一個模擬服務器替換真實的服務器,並使用 Wiremock 來實現這個目的。
WireMock 是一個開源的用於模擬 Web 服務的庫。 它允許我們創建樁,用於測試客户端與服務器之間的交互。
讓我們將 Wiremock 庫添加到我們的 pom.xml 中:
<dependency>
<groupId>org.wiremock</groupId>
<artifactId>wiremock-standalone</artifactId>
<version>3.9.1</version>
<scope>test</scope>
</dependency>我們現在可以將 Wiremock 服務器配置到我們的 JUnit 測試中。我們將使其在每個測試方法之前啓動,並在每個測試方法之後停止:
private WireMockServer wireMockServer;
@BeforeEach
void startServer() {
wireMockServer = new WireMockServer();
wireMockServer.start();
}
@AfterEach
void stopServer() {
wireMockServer.stop();
}4. 使用 RestAssured 發送文件
我們將快速設置我們的模擬服務器,然後轉向編寫 RestAssured 測試。
4.1. 文件處理
讓我們創建一個名為 baeldung.txt 的文件,位於 test/resources 目錄下。 為了準備文件發送,我們先編寫兩個實用方法:
- 給定一個文件名,getFile() 方法會檢索相應的 File 對象
- getFileContent() 方法會讀取文件內容
以下是我們的方法:
File getFile(String fileName) throws IOException {
return new ClassPathResource(fileName).getFile();
}
String getFileContent(String fileName) throws IOException {
return new String(Files.readAllBytes(Paths.get(getFile(fileName).getPath())));
}4.2. 樁服務器創建
我們將將 baeldung.txt 文件發送到 URL /upload。 我們將將 file 設置為 multipart 請求中文件的控制名稱。
首先,我們將創建一個期望接收此類請求的樁服務器。 此外,我們還將檢查 Content-Type 請求頭是否為 multipart/form-data。 當請求滿足所有這些條件時,我們將使用 200 響應狀態代碼進行響應:
stubFor(post(urlEqualTo("/upload"))
.withHeader("Content-Type", containing("multipart/form-data"))
.withRequestBody(containing("file"))
.withRequestBody(containing(getFileContent("baeldung.txt")))
.willReturn(aResponse().withStatus(200)));4.3. RestAssured 測試請求
現在,我們將專注於發送到服務器的多部分請求。藉助 RestAssured,請求規範遵循給定的“先-然後”範式。
首先,我們將使用 multipart() 方法來添加多部分請求。 讓我們看看它的參數:
- file,與請求中的文件關聯的控制名稱
- 文件內容
然後,我們將使用 post() 方法發出 HTTP POST 請求。 它的參數是 /upload 目標 URL。 最後,我們將使用 statusCode() 方法設置預期響應狀態碼。
given()
.multiPart("file", getFile("/baeldung.txt"))
.when()
.post("/upload")
.then()
.statusCode(200);我們現在可以測試此請求與之前的樁程序是否一致:狀態碼正確!
通過反覆調用 multipart() 方法,可以向測試請求添加更多文件。例如,我們可以添加一個名為 helloworld.txt 的新文件,並將對應的部分命名為 helloworld。
given()
.multiPart("file", getFile("/baeldung.txt"))
.multiPart("helloworld", getFile("/helloworld.txt"))
.when()
.post("/upload")
.then()
.statusCode(200);5. 構建自定義多部分規範
有時,我們希望在請求中提供更詳細的多部分內容。讓我們看看如何做到這一點。
5.1. Wiremock 樁服務器更新
讓我們快速更新我們的 Wiremock 樁服務器。 這一次,我們將期望請求包含一個名為 file 的multipart 類型。 文件名將是 file.txt。 請求的 Content-Type 頭部將是 text/plain,並且請求體將包含 File content。
我們將使用 MultipartValuePatternBuilder 來完成我們的 mock 服務器規範:
MultipartValuePatternBuilder multipartValuePatternBuilder = aMultipart()
.withName("file")
.withHeader("Content-Disposition", containing("file.txt"))
.withBody(equalTo("File content"))
.withHeader("Content-Type", containing("text/plain"));
stubFor(post(urlEqualTo("/upload"))
.withMultipartRequestBody(multipartValuePatternBuilder)
.willReturn(aResponse().withStatus(200)));5.2. 多部分規範
現在我們來編寫測試請求。 藉助 RestAssured 庫中的 <em >MultipartSpecification</em> 類,我們可以設置控制名稱,只要名稱、MIME 類型、字符集和文件內容都正確,即可。 控制名稱在服務器端標識該部分,而文件名由發送者設置。
因此,我們將構建一個簡單的示例,其中:
- 該部分被稱為 `file`
- 給文件的名稱是 `file.txt`
- 文件的 MIME 類型是 `text/plain`
作為結果,請求的 <em >Content-Type</em> 是 <em >text/plain</em>,而不是 <em >multipart/form-data</em>。 然而,這仍然是一個多部分請求,因為內容被編碼在其中一個部分內。 此外,我們不需要使用磁盤上的現有文件。 為了展示這一點,我們將從一個 <em >String</em> 中生成內容:
MultiPartSpecification multiPartSpecification = new MultiPartSpecBuilder("File content".getBytes())
.fileName("file.txt")
.controlName("file")
.mimeType("text/plain")
.build();我們現在可以使用重載方法 multipart() 直接傳入 MultipartSpecification 作為參數來更新我們的 RestAssured 請求規範:
given()
.multiPart(multiPartSpecification)
.when()
.post("/upload")
.then()
.statusCode(200);我們現在知道如何為我們的 RestAssured 多部分請求增加更多粒度。
6. 結論
在本文中,我們使用 RestAssured 向一個模擬服務器發送多部分請求。
我們學習瞭如何僅通過內容發送文件並控制名稱,然後轉向構建更復雜的組成部分。