如何测试需要soap Headers的Spring-WS Web服务?

时间:2011-08-30 23:51:26

标签: java integration-testing spring-ws

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

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

如何访问正在生成的soap请求以获取正确的标头?

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

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

3 个答案:

答案 0 :(得分:2)

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

创建一个拦截器,我实现了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服务。

答案 1 :(得分:0)

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

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

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

答案 2 :(得分:0)

如您所述,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响应(标头和正文)。