1、简介 {#1简介}
本文将带你了解如何使用 @WebServiceServerTest
为 Spring Boot 开发的 SOAP Web Service 编写集成测试。
2、测试 Spring Web Service {#2测试-spring-web-service}
在 Spring Web Service 中,端点是服务器端 Service 实现的关键概念。专门的 @Endpoint
注解将类标记为 Web Service 端点。这些端点负责接收 XML 请求消息、调用所需的业务 Service 并将结果作为响应消息返回。
2.1、Spring Web Service 的测试支持 {#21spring-web-service-的测试支持}
为了测试此类端点,我们可以通过传递所需的参数或模拟(Mock)来轻松创建单元测试。然而,这样做的主要缺点是无法实际测试通过网络发送的 XML 消息的内容。另一种方法是创建集成测试,以验证消息的 XML 内容。
Spring Web Service 2.0 引入了对此类端点集成测试的支持。提供这种支持的核心类是 MockWebServiceClient
。它提供了一个 Fluent API,用于向 Spring Application Context 中配置的适当端点发送 XML 消息。此外,我们还可以设置响应预期、验证响应 XML,并对端点执行完整的集成测试。
不过,这需要调用整个 Application Context,从而减慢测试执行速度。这通常是不可取的,尤其是当我们希望为特定 Web Service 端点创建快速、隔离的测试时。
2.2、Spring Boot @WebServiceServerTest
{#22spring-boot-webserviceservertest}
Spring Boot 2.6 通过 @WebServiceServerTest
注解扩展了 Web Service 测试支持。
我们可以将其用于仅关注 Web Service 而非加载整个 Application Context 的测试。换句话说,我们可以创建一个只包含所需 @Endpoint
Bean 的测试片段,并使用 @MockBean
来模拟任何依赖。
这与 Spring Boot 已经提供的便捷测试片段注解(如 @WebMvcTest
、@DataJpaTest
等)非常相似。
3、建立示例项目 {#3建立示例项目}
3.1、依赖 {#31依赖}
除了 Web Service 必须依赖外,还需要额外的 spring-ws-test
依赖(test
scope):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-test</artifactId>
<version>3.1.3</version>
<scope>test</scope>
</dependency>
3.2、Web Service 示例 {#32web-service-示例}
接下来,创建一个简单的服务,为指定的 Product ID 返回一些 Product 数据:
@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
方法接收 request
对象,并从 Repository 中获取 Product 数据,然后返回响应。Repository 的细节在这里并不重要。在本例中,为了简单,可以使用一个简单的内存实现。
4、端点测试 {#4端点测试}
最后,创建一个测试片段,验证 Web Service 对 XML 消息的正确处理:
@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。换句话说,这个测试片段创建了一个精简的 Application Context。这帮助我们构建有针对性且快速的集成测试,而不会因为反复加载整个 Application Context 而影响性能。
重要的是,该注解还配置了一个 MockWebServiceClient
以及其他相关的自动配置。因此,我们可以将该客户端注入到我们的测试中,并用它来发送 getProductRequest
XML 请求,然后进行各种 Fluent 式的期望操作。
预期(Expectation)验证响应 XML 是否与给定的 XSD schema 匹配,并且与预期的 XML 响应相匹配。还可以使用 XPath 表达式来评估和比较响应 XML 中的各种值。
4.1、Endpoint 的依赖 {#41endpoint-的依赖}
在这个示例中,我们使用 @MockBean
来模拟 ProductEndpoint
所需的 Repository。如果没有这个模拟,Application Context 就无法启动,因为自动配置被禁用了。换句话说,测试框架不会在测试执行前配置任何 @Component
、@Service
或 @Repository
Bean。
不过,如果我们确实需要实际的组件依赖,而不是模拟,那么可以使用 @Import
声明这些组件。Spring 会查找这些类,然后根据需要将它们注入到端点中。
4.2、加载整个 Context {#42加载整个-context}
如前所述,@WebServiceServerTest
不会加载整个 Application Context。如果我们确实需要加载整个 Application Context 进行测试,那么我们应该考虑把 @SpringBootTest
与 @AutoConfigureMockWebServiceClient
结合使用。然后,可以以类似的方式使用该客户端来发送请求并验证响应,如前所述。
5、总结 {#5总结}
本文介绍了 Spring Boot 中引入的 @WebServiceServerTest
注解,以及如何使用它为 Spring Boot 开发的 SOAP Web Service 构建快速、集中的集成测试。
参考:https://www.baeldung.com/spring-webserviceservertest