1. 概述
在本教程中,我們將使用 RestAssured 庫向服務器發送多部分請求。這對於測試 Spring 中的多部分控制器或針對已部署服務器編寫集成測試非常有用。
2. 什麼是多部分請求?
在多部分請求中,數據被分成多個部分。 每個部分都有一個名稱和一組自己的標頭,指示其包含的數據類型。 數據和每個部分之間的邊界進行編碼。
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 測試請求
現在是時候專注於我們將發送到服務器的 multipart 請求。 使用 RestAssured,請求規範遵循給-定-當-然範式。
首先,我們將使用 multipart() 方法添加 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 模擬服務器。 這一次,我們將期望請求包含一個名為 file的多部分內容。文件名將是 file.txt。請求的 Content-Type 標頭將是 text/plain,並且主體將包含 File content。
我們將使用 MultipartValuePatternBuilder 來完成我們的模擬服務器規範:
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 庫中的 MultipartSpecification 類,我們可以將控制名稱設置為名稱、MIME 類型、字符集和文件內容。控制名稱在服務器端標識部分,而文件名由發送方設置。
因此,我們將構建一個簡單的示例,其中:
- 該部分將被命名為 file
- 給文件的名稱是 file.txt
- 文件的 MIME 類型是 text/plain
因此,請求的 Content-Type 是 text/plain,而不是 multipart/form-data。儘管如此,這仍然是一個多部分請求,因為內容已編碼在部分中。 此外,我們不需要使用磁盤上的現有文件。 為了展示這一點,我們將從一個 String 生成內容:
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 向一個模擬服務器發送多部分請求。
我們看到了如何僅通過內容發送文件並控制名稱,然後切換到構建更復雜的組成部分。