1. 簡介
本文將介紹如何為使用 Spring Boot 構建的 SOAP Web 服務編寫集成測試。
我們已經知道如何為應用程序類編寫單元測試,並且我們已經在 Spring Boot 中的測試教程中涵蓋了通用的測試概念。因此,在這裏,我們將重點關注僅使用 <em @WebServiceServerTest</em>> 模塊測試 Web 服務層面的集成測試。
2. 測試 Spring Web 服務
在 Spring Web 服務中,端點是服務端服務實現的關鍵概念。 專門的 <em @Endpoint</em> 註解標記了被註解的類為一個 Web 服務端點。 重要的是,這些 端點負責接收 XML 請求消息、調用所需的業務邏輯,並以響應消息返回結果。
2.1. Spring Web Services 測試支持
為了測試這些端點,我們可以通過傳遞所需的參數或模擬對象輕鬆創建單元測試。然而,主要缺點是這種方法並不能真正測試通過網絡發送的 XML 消息的內容。另一種方法是創建集成測試,這些測試確實可以驗證消息的 XML 內容。
Spring Web Services 2.0 引入了對這些端點的集成測試支持。核心類,該類提供此支持,是 MockWebServiceClient。它提供了一個流暢的 API,用於將 XML 消息發送到 Spring 應用程序上下文配置的適當端點。此外,我們還可以設置響應期望、驗證響應 XML 以及對我們的端點執行完整的集成測試。
但是,這需要啓動整個應用程序上下文,從而導致測試執行速度變慢。這在創建針對特定 Web 服務端點的快速且隔離的測試時尤其不理想。
2.2. Spring Boot <em @WebServiceServerTest
Spring Boot 2.6 通過使用 <em @WebServiceServerTest 註解擴展了 Web 服務測試支持。
我們可以使用它來執行 僅關注 Web 服務層,而無需加載整個應用程序上下文的測試。換句話説,我們可以創建一個只包含必需的 <em @Endpoint Bean 的測試片段,並使用 <em @MockBean 模擬任何依賴項。
這與 Spring Boot 提供的便捷測試片段註解非常相似,例如 <em @WebMvcTest、<em @DataJpaTest 以及其他各種註解。
3. 設置示例項目
This section describes how to set up the example project. You will need to clone the repository and install the necessary dependencies.
Prerequisites
- Git
- Node.js (v16 or higher)
- npm or yarn
Installation
-
Clone the repository:
git clone [repository URL] -
Navigate to the project directory:
cd [project directory name] -
Install the dependencies:
npm install # or yarn install -
Verify the installation:
npm run build # or yarn build
3.1. 依賴項
鑑於我們之前已經對 Spring Boot Web 服務項目進行了詳細説明,這裏我們只需添加用於我們項目所需的額外測試範圍的 <a href="https://mvnrepository.com/artifact/org.springframework.ws/spring-ws-test">spring-ws-test</a> 依賴項:
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-test</artifactId>
<version>4.0.10</version>
<scope>test</scope>
</dependency>3.2. 示例 Web 服務
接下來,讓我們創建一個簡單的服務,用於返回指定的產品 ID 的產品數據:
@Endpoint
public class ProductEndpoint {
@Autowired
private ProductRepository productRepository;
@ResponsePayload
public GetProductResponse getProduct(@RequestPayload GetProductRequest request) {
GetProductResponse response = new GetProductResponse();
response.setProduct(productRepository.findProduct(request.getId()));
return response;
}
}在這裏,我們對 ProductEndpoint 組件進行了標註,使用了 @Endpoint 註解,使其能夠處理相應的 XML 請求。
getProduct 方法接收請求對象,並從一個倉庫中獲取產品數據,然後再返回響應。 倉庫的細節在這裏並不重要。 在我們的情況下,我們可以使用一個簡單的內存實現,以保持應用程序的簡潔,並專注於我們的測試策略。
4. 端點測試
最後,我們可以創建測試切片並驗證 XML 消息在 Web 服務層中的正確處理:
@WebServiceServerTest
class ProductEndpointIntegrationTest {
@Autowired
private MockWebServiceClient client;
@MockBean
private ProductRepository productRepository;
@Test
void givenXmlRequest_whenServiceInvoked_thenValidResponse() throws IOException {
Product product = createProduct();
when(productRepository.findProduct("1")).thenReturn(product);
StringSource request = new StringSource(
"<bd:getProductRequest xmlns:bd='http://baeldung.com/spring-boot-web-service'>" +
"<bd:id>1</bd:id>" +
"</bd:getProductRequest>"
);
StringSource expectedResponse = new StringSource(
"<bd:getProductResponse xmlns:bd='http://baeldung.com/spring-boot-web-service'>" +
"<bd:product>" +
"<bd:id>1</bd:id>" +
"<bd:name>Product 1</bd:name>" +
"</bd:product>" +
"</bd:getProductResponse>"
);
client.sendRequest(withPayload(request))
.andExpect(noFault())
.andExpect(validPayload(new ClassPathResource("webservice/products.xsd")))
.andExpect(payload(expectedResponse))
.andExpect(xpath("/bd:getProductResponse/bd:product[1]/bd:name", NAMESPACE_MAPPING)
.evaluatesTo("Product 1"));
}
}在這裏,我們僅配置了帶有 @Endpoint 註解的 Bean,用於我們的集成測試。換句話説,這個測試切片創建一個簡化的應用程序上下文。這有助於我們構建針對性強、快速的集成測試,而無需重複加載整個應用程序上下文所帶來的性能懲罰。
重要的是,這個註解也配置了一個 MockWebServiceClient,以及其他相關的自動配置。因此,我們可以將這個客户端連接到我們的測試中,並使用它來發送 getProductRequest XML 請求,然後跟隨各種 Fluent 期望。
這些期望驗證響應 XML 與給定的 XSD 模式進行驗證,並且與預期的 XML 響應匹配。我們還可以使用 XPath 表達式來評估和比較響應 XML 中的各種值。
4.1. 端點協作者
在我們的示例中,我們使用了 <em @MockBean</em> 來模擬 <em ProductEndpoint</em>> 中所需的倉庫。缺少此模擬,應用程序上下文無法啓動,因為全自動配置已禁用。換句話説,<strong>測試框架在執行測試之前不會配置任何<em>@Component</em>、<em>@Service</em> 或 <em>@Repository</em> 類型的 Bean</strong>。
但是,如果我們確實需要使用實際的協作者而不是模擬,則可以使用 <em @Import</em> 聲明它們。Spring 將查找這些類,然後將它們連接到端點,如需要。
4.2. 加載整個上下文
正如之前所述,<em@WebServiceServerTest</em>> 將不會加載整個應用程序上下文。如果確實需要為測試加載整個應用程序上下文,那麼我們應該考慮使用 <em@SpringBootTest</em>> 與 <em@AutoConfigureMockWebServiceClient</em> 結合使用。 這樣,我們就可以像之前一樣,使用該客户端發送請求並驗證響應。
5. 結論
在本文中,我們探討了 Spring Boot 中引入的 <em @WebServiceServerTest</em> 註解。
最初,我們討論了在 Web 服務應用程序中 Spring Boot 的測試支持。隨後,我們看到了如何使用此註解創建 Web 服務層面的測試模塊,從而構建快速且聚焦的集成測試。