【问题标题】:How do I test a Spring-WS webservice that Requires soapHeaders?如何测试需要soap Headers 的Spring-WS Web 服务?
【发布时间】:2011-08-30 23:51:25
【问题描述】:

我已经实现了一个 spring-ws (2.0.2) 服务,它需要在 soap 标头中添加一些自定义元素。我正在尝试使用 Spring 的 MockWebServiceClient 生成一个有效的请求来测试调度程序、编组器等。

我遇到的问题是 MockWebSerivce 似乎只支持 Soap Body(有效负载)。

如何访问正在生成的soap 请求以将正确的标头放入其中?

如果除了 Spring 的 MockWebServiceClient 之外还有更好的库来执行此操作,那也很好。

相关链接: http://forum.springsource.org/showthread.php?101708-MockWebServiceClient-amp-WS-Security
Add SoapHeader to org.springframework.ws.WebServiceMessage

【问题讨论】:

    标签: java integration-testing spring-ws


    【解决方案1】:

    当我想使用 Security 测试 Spring Web 服务时遇到了类似的问题,我最终使用 Spring 拦截器在它们到达终点之前修改标头,我启用拦截器仅用于测试。

    创建一个拦截器,我实现了SmartEndpointInterceptor,你可以选择使用其他拦截器

    public class ModifySoapHeaderInterceptor implements
        SmartEndpointInterceptor 
    {
      //WSConstants.WSSE_NS;
       private static final String DEFAULT_SECURITY_URL = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
        private static final String SECURITY_TAG = "Security";
        private static final String SECURITY_PREFIX = "wsse";
        private static final String USER_NAME_TOKEN = "UsernameToken";
    
        @Override
    public boolean handleRequest(MessageContext messageContext, Object endpoint)
            throws Exception 
    {
          SaajSoapMessage saajSoapMessage(SaajSoapMessage)messageContext.getRequest());
          SOAPHeader soapHeader = saajSoapMessage.getSaajMessage().getSOAPPart()
                .getEnvelope().getHeader();
    
           //you can modify header's as you choose
           Name headerElement = saajSoapMessage.getSaajMessage().getSOAPPart()
                .getEnvelope()
                .createName(SECURITY_TAG, SECURITY_PREFIX, DEFAULT_SECURITY_URL);
           SOAPHeaderElement soapHeaderElement = soapHeader
                .addHeaderElement(headerElement);
        SOAPElement usernameToken = soapHeaderElement.addChildElement(
                USER_NAME_TOKEN, SECURITY_PREFIX);
    
        SOAPElement userNameElement = usernameToken.addChildElement("Username",
                SECURITY_PREFIX);
        userNameElement.addTextNode("userid");//you can inject via spring
    
        SOAPElement passwordElement = usernameToken.addChildElement("Password",
                SECURITY_PREFIX);
        passwordElement.addTextNode("password");
           return true;
        }
    }
    

    在spring上下文中配置这个拦截器

      <sws:interceptors>
         <bean class="prasanna.ws.security.wss4j.ModifySoapHeaderInterceptor"/>
      </sws:interceptors>
    

    这将在消息到达终点之前将必要的安全标头添加到消息中,您仍然可以使用 MockWebServiceClient 来测试您的 Web 服务。

    【讨论】:

    • 非常感谢。由于我使用替代 context.xml 进行测试,其中包括我的生产环境,我可以将拦截器放在我假设的那个上下文中。
    【解决方案2】:

    正如您所指出的,MockWebServiceClient sendRequest() 方法仅使用给定的有效负载设置 SOAP 主体。它不会触及 SOAP 标头。

    要同时设置 SOAP 标头,您可以创建一个实现 RequestCreator 接口并设置 SOAP 标头的类。将此类的实例传递给 sendRequest() 方法。

    例如:

    class SoapActionCreator implements RequestCreator {
    
        private final Source payload;
    
        public SoapActionCreator(Source payload) {
            this.payload = payload;
        }
    
        @Override
        public WebServiceMessage createRequest(WebServiceMessageFactory webServiceMessageFactory)
                throws IOException {
            WebServiceMessage webServiceMessage =
                    new PayloadMessageCreator(payload).createMessage(webServiceMessageFactory);
    
            SoapMessage soapMessage = (SoapMessage) webServiceMessage;
            SoapHeader header = soapMessage.getSoapHeader();
            // Add an Action element to the SOAP header
            StringSource headerSource = new StringSource(
                    "<wsa:Action xmlns:wsa=\"http://www.w3.org/2005/08/addressing\">https://example.com/foo/bar</wsa:Action>");
            Transformer transformer = TransformerFactory.newInstance().newTransformer();
            transformer.transform(headerSource, header.getResult());
    
            return webServiceMessage;
        }
    

    }

    然后像这样使用SoapActionCreator

        SoapActionCreator soapActionCreator = new SoapActionCreator(requestPayload);
        mockClient.sendRequest(soapActionCreator).
                andExpect(payload(responsePayload));
    

    其中requestPayload 是 SOAP 请求正文,responsePayload 是整个 SOAP 响应(标头和正文)。

    【讨论】:

      【解决方案3】:

      我确实找到了 smock 库,它可以做我真正想要的:只需要一个包含整个请求的文本文件。

      http://code.google.com/p/smock/wiki/SpringWs

      它支持与 spring 提供的东西相同的请求和响应匹配器。它还使我的测试非常独立。 (而不是只在我的测试用例中使用的全新类。)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-23
        • 1970-01-01
        • 2019-04-08
        • 1970-01-01
        相关资源
        最近更新 更多