使用 @WebServiceServerTest 的 Spring Web 服務集成測試
- Spring
一、簡介
在本文中,我們將了解如何為使用 Spring Boot 構建的 SOAP Web 服務編寫集成測試。
我們已經知道如何為應用程序類編寫單元測試,並且我們已經在 Spring Boot 測試教程中介紹了一般測試概念。因此,在這裡,我們將專注於使用@WebServiceServerTest
僅對 Web 服務層進行集成測試。
2 測試 Spring Web 服務
在 Spring Web Services 中,端點是服務器端服務實現的關鍵概念。專門的@Endpoint
註釋將帶註釋的類標記為 Web 服務端點。重要的是,這些端點負責接收 XML 請求消息,調用所需的業務邏輯,並將結果作為響應消息返回。
2.1 Spring Web 服務測試支持
為了測試這樣的端點,我們可以通過傳入所需的參數或模擬來輕鬆創建單元測試。然而,主要的缺點是這實際上並沒有測試通過網絡發送的 XML 消息的內容。另一種方法是創建確實驗證消息的 XML 內容的集成測試。
Spring Web Services 2.0 引入了對此類端點的集成測試的支持。提供這種支持的核心類是MockWebServiceClient
。它提供了一個流暢的 API 來將 XML 消息發送到 Spring 應用程序上下文中配置的適當端點。此外,我們可以設置響應預期、驗證響應 XML 並為我們的端點執行完整的集成測試。
但是,這需要調出整個應用程序上下文,這會減慢測試執行速度。這通常是不可取的,特別是如果我們希望為特定的 Web 服務端點創建快速和隔離的測試。
2.2. Spring Boot @WebServiceServerTest
Spring Boot 2.6 使用@WebServiceServerTest
註解擴展了 Web 服務測試支持。
我們可以將其用於僅關注 Web 服務層而不是加載整個應用程序上下文的測試。換句話說,我們可以創建一個僅包含所需@Endpoint
bean 的測試切片,並且我們可以使用@MockBean
模擬任何依賴項。
這與 Spring Boot 已經提供的方便的測試切片註釋非常相似,例如@WebMvcTest
、 @DataJpaTest,
和其他各種註釋。
3. 設置示例項目
3.1。依賴項
由於我們已經詳細介紹了 Spring Boot Web 服務項目,因此我們將僅包含項目所需的額外測試範圍spring-ws-test依賴項:
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-test</artifactId>
<version>3.1.3</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;
}
}
在這裡,我們使用@Endpoint,
對ProductEndpoint
組件進行了註釋,它註冊它以處理適當的 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 請求,然後是各種流暢的期望。
期望驗證響應 XML 是否針對給定的 XSD 模式進行驗證,並且它與預期的 XML 響應匹配。我們還可以使用 XPath 表達式來評估和比較響應 XML 中的各種值。
4.1 端點合作者
在我們的示例中,我們使用@MockBean
來模擬ProductEndpoint
中所需的存儲庫。如果沒有這個模擬,應用程序上下文將無法啟動,因為完全自動配置被禁用。換句話說,測試框架在測試執行之前沒有配置任何@Component、 @Service,
@Repository
@Component
。
但是,如果我們確實需要任何實際的協作者而不是模擬,那麼我們可以使用@Import
聲明它們。 Spring 將查找這些類,然後根據需要將它們連接到端點。
4.2.加載整個上下文
如前所述, @WebServiceServerTest
不會加載整個應用程序上下文。如果我們確實需要為測試加載整個應用程序上下文,那麼我們應該考慮將@SpringBootTest
結合使用@AutoConfigureMockWebServiceClient.
然後,我們可以以類似的方式使用此客戶端發送請求並驗證響應,如前所示。
5. 結論
在本文中,我們查看了 Spring Boot 中引入的@WebServiceServerTest
註解。
最初,我們討論了 Web 服務應用程序中的 Spring Boot 測試支持。接下來,我們看到瞭如何使用此註解為 Web 服務層創建測試切片,這有助於構建快速且集中的集成測試。