spring ws MockWebServiceClient 响应的有效负载源

发布于 2024-11-14 13:45:40 字数 6741 浏览 6 评论 0原文

我正在使用 spring-ws 2.0.2 和 spring-ws-test 来运行 SOAP 服务器的集成测试。我使用的方法与 http://static.springsource.org/spring-ws/site/apidocs/org/springframework/ws/test/server/MockWebServiceClient.html

这是我正在运行的代码,具有预期的响应为简洁起见,省略了 XML,因为它与问题无关。

我希望能够在响应负载中看到 xml,但不知道如何访问它。如果我在设置响应后设置断点并检查它,我可以看到它有一个 SaajSoapMessage 类型的私有 messageContext.response,但我不知道如何访问它,也不知道是否有更好的方法来查看响应 XML。

package com.example.integration;                                                                     

import static org.springframework.ws.test.server.RequestCreators.*;                                 
import static org.springframework.ws.test.server.ResponseMatchers.*;                                
import static org.testng.AssertJUnit.*;                                                             

import javax.xml.transform.Source;                                                                  

import org.springframework.beans.factory.annotation.Autowired;                                      
import org.springframework.context.ApplicationContext;                                              
import org.springframework.ws.test.server.MockWebServiceClient;                                     
import org.springframework.ws.test.server.ResponseActions;                                          
import org.springframework.xml.transform.StringSource;                                              
import org.testng.annotations.BeforeClass;                                                          
import org.testng.annotations.Test;                                                                 

@ContextConfiguration(locations={"/transaction-test-context.xml", "/spring-web-services-servlet.xml"})
public class BaseWebServiceIntegrationTest {                          

    @Autowired
    private ApplicationContext applicationContext;

    private MockWebServiceClient mockClient;

    @BeforeClass(groups="integration")
    public void createClient() {
        assertNotNull("expected applicationContext to be non-null", applicationContext);
        mockClient = MockWebServiceClient.createClient(applicationContext);
    }

    @Test(groups="integration")
    public void proofOfConcept() {

        assertNotNull("expected mockClient to be non-null", mockClient);

        Source requestPayload = new StringSource(
                "<s0:ListDevicesRequest " +
                "xmlns:soapenc='http://schemas.xmlsoap.org/soap/encoding/' " +
                "xmlns:xs='http://www.w3.org/2001/XMLSchema' " +
                "xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' " +
                "xmlns:s0='urn:com:example:xmlschema:service:v1.1:DeviceManager.xsd'>" +
                    "<s0:MacID>66:bb:be:ee:00:00:01:00</s0:MacID>" +
                "</s0:ListDevicesRequest>"
                );

        Source responsePayload = new StringSource("<!-- response omitted for the post, not relevant -->");

        ResponseActions response = mockClient.sendRequest(withPayload(requestPayload));
        response.andExpect(noFault())
                .andExpect(payload(responsePayload));

    }
}

编辑以根据要求添加应用程序上下文文件。我们有一些,但下面的是肥皂专用的。

<?xml version="1.0"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:sec="http://www.springframework.org/schema/security"
       xsi:schemaLocation="
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <sec:global-method-security pre-post-annotations="disabled" jsr250-annotations="disabled" />

    <tx:annotation-driven/>
    <context:component-scan base-package="com.example.integration"/>
    <context:component-scan base-package="com.example.signal"/>

    <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>

    <bean id="faultService" class="com.example.webservice.fault.FaultService"/>

    <bean id="soapDeviceService" class="com.example.webservice.device.SoapDeviceServiceImpl"/>


    <!-- 1.1 Endpoints -->
    <bean id="deviceManagerEndpoint_v1_1" class="com.example.webservice.spring.DeviceManagerEndpoint">
        <property name="soapDeviceService" ref="soapDeviceService"/>
    </bean>



    <bean class="com.example.webservice.spring.PayloadMethodMarshallingEndpointAdapter">
        <property name="marshaller" ref="marshaller"/>
        <property name="unmarshaller" ref="marshaller"/>
    </bean>
    <bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
        <property name="mtomEnabled" value="false"/>
        <property name="contextPath" value="com.example.xmlschema.service.v1_0.devicemanager"/>
    </bean>

    <bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping">
        <property name="interceptors">
            <list>
                <bean class="com.example.webservice.interceptor.LoggingInterceptor"/>
                <ref bean="validatingInterceptor"/>
            </list>
        </property>
    </bean>

    <bean id="validatingInterceptor" class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor">
        <property name="schemas">
            <list>
                <value>/WEB-INF/wsdl/*Types_v*.xsd</value>
            </list>
        </property>
        <property name="validateRequest" value="true"/>
        <property name="validateResponse" value="true"/>
    </bean>

    <bean class="com.example.webservice.spring.SpringWebserviceFaultMappingExceptionResolver">
        <property name="order" value="1"/>
        <property name="marshaller" ref="marshaller"/>
    </bean>

</beans>

I'm using spring-ws 2.0.2 and spring-ws-test to run integration tests of my SOAP server. I'm using an approach exactly like that from http://static.springsource.org/spring-ws/site/apidocs/org/springframework/ws/test/server/MockWebServiceClient.html

Here's the code I'm running with the expected response XML omitted for brevity and because it's not relevant to the question.

I'd like to be able to see the xml in the response payload but can't figure out how to get access to it. If I set a breakpoint after response is set and inspect it I can see that it has a private messageContext.response of type SaajSoapMessage but I can't figure out how to access it or if there's a better way to see the response XML.

package com.example.integration;                                                                     

import static org.springframework.ws.test.server.RequestCreators.*;                                 
import static org.springframework.ws.test.server.ResponseMatchers.*;                                
import static org.testng.AssertJUnit.*;                                                             

import javax.xml.transform.Source;                                                                  

import org.springframework.beans.factory.annotation.Autowired;                                      
import org.springframework.context.ApplicationContext;                                              
import org.springframework.ws.test.server.MockWebServiceClient;                                     
import org.springframework.ws.test.server.ResponseActions;                                          
import org.springframework.xml.transform.StringSource;                                              
import org.testng.annotations.BeforeClass;                                                          
import org.testng.annotations.Test;                                                                 

@ContextConfiguration(locations={"/transaction-test-context.xml", "/spring-web-services-servlet.xml"})
public class BaseWebServiceIntegrationTest {                          

    @Autowired
    private ApplicationContext applicationContext;

    private MockWebServiceClient mockClient;

    @BeforeClass(groups="integration")
    public void createClient() {
        assertNotNull("expected applicationContext to be non-null", applicationContext);
        mockClient = MockWebServiceClient.createClient(applicationContext);
    }

    @Test(groups="integration")
    public void proofOfConcept() {

        assertNotNull("expected mockClient to be non-null", mockClient);

        Source requestPayload = new StringSource(
                "<s0:ListDevicesRequest " +
                "xmlns:soapenc='http://schemas.xmlsoap.org/soap/encoding/' " +
                "xmlns:xs='http://www.w3.org/2001/XMLSchema' " +
                "xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' " +
                "xmlns:s0='urn:com:example:xmlschema:service:v1.1:DeviceManager.xsd'>" +
                    "<s0:MacID>66:bb:be:ee:00:00:01:00</s0:MacID>" +
                "</s0:ListDevicesRequest>"
                );

        Source responsePayload = new StringSource("<!-- response omitted for the post, not relevant -->");

        ResponseActions response = mockClient.sendRequest(withPayload(requestPayload));
        response.andExpect(noFault())
                .andExpect(payload(responsePayload));

    }
}

edited to add the application context file as requested. we have a few but the one below is the soap-specific one.

<?xml version="1.0"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:sec="http://www.springframework.org/schema/security"
       xsi:schemaLocation="
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

    <sec:global-method-security pre-post-annotations="disabled" jsr250-annotations="disabled" />

    <tx:annotation-driven/>
    <context:component-scan base-package="com.example.integration"/>
    <context:component-scan base-package="com.example.signal"/>

    <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>

    <bean id="faultService" class="com.example.webservice.fault.FaultService"/>

    <bean id="soapDeviceService" class="com.example.webservice.device.SoapDeviceServiceImpl"/>


    <!-- 1.1 Endpoints -->
    <bean id="deviceManagerEndpoint_v1_1" class="com.example.webservice.spring.DeviceManagerEndpoint">
        <property name="soapDeviceService" ref="soapDeviceService"/>
    </bean>



    <bean class="com.example.webservice.spring.PayloadMethodMarshallingEndpointAdapter">
        <property name="marshaller" ref="marshaller"/>
        <property name="unmarshaller" ref="marshaller"/>
    </bean>
    <bean id="marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
        <property name="mtomEnabled" value="false"/>
        <property name="contextPath" value="com.example.xmlschema.service.v1_0.devicemanager"/>
    </bean>

    <bean class="org.springframework.ws.server.endpoint.mapping.PayloadRootAnnotationMethodEndpointMapping">
        <property name="interceptors">
            <list>
                <bean class="com.example.webservice.interceptor.LoggingInterceptor"/>
                <ref bean="validatingInterceptor"/>
            </list>
        </property>
    </bean>

    <bean id="validatingInterceptor" class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor">
        <property name="schemas">
            <list>
                <value>/WEB-INF/wsdl/*Types_v*.xsd</value>
            </list>
        </property>
        <property name="validateRequest" value="true"/>
        <property name="validateResponse" value="true"/>
    </bean>

    <bean class="com.example.webservice.spring.SpringWebserviceFaultMappingExceptionResolver">
        <property name="order" value="1"/>
        <property name="marshaller" ref="marshaller"/>
    </bean>

</beans>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

隐诗 2024-11-21 13:45:40

好吧,晚了 4 年,但这是我的答案,我对此感到既自豪又感到羞愧 :-

.andExpect(
    new ResponseMatcher()
    {
        @Override
        public void match(WebServiceMessage request, WebServiceMessage response)
            throws IOException, AssertionError
        {
            response.writeTo(System.out);
        }
    })

自 Java 8 以来:

.andExpect((request, response) -> response.writeTo(System.out))

Ok, 4 years too late, but here is my answer, which I am both proud and ashamed of :-

.andExpect(
    new ResponseMatcher()
    {
        @Override
        public void match(WebServiceMessage request, WebServiceMessage response)
            throws IOException, AssertionError
        {
            response.writeTo(System.out);
        }
    })

And since Java 8:

.andExpect((request, response) -> response.writeTo(System.out))
撞了怀 2024-11-21 13:45:40

您可以在 spring-ws 上下文中安装 PayloadLoggingInterceptor,默认情况下它将记录所有请求和响应负载。像这样配置它:

<sws:interceptors>
  <bean class="org.springframework.ws.server.endpoint.interceptor.PayloadLoggingInterceptor"/>
</sws:interceptors>

查看 springsource 文档以获取更多信息
此处

You could install a PayloadLoggingInterceptor in your spring-ws context which will by default log all request and response payloads. Configure it like this:

<sws:interceptors>
  <bean class="org.springframework.ws.server.endpoint.interceptor.PayloadLoggingInterceptor"/>
</sws:interceptors>

Check out the springsource docs for more info
here

葮薆情 2024-11-21 13:45:40

配置log4j并在log4j中添加配置以显示spring类日志。日志将显示 Spring 类的调用顺序以及发送的请求和响应。

<logger name="org.springframework.ws" additivity="false">
   <level value="DEBUG#org.tiaa.infra.logging.TiaaLevel" />
   <appender-ref ref="DailyRollingFileAppender"/>
</logger>

Configure log4j and add configuration in log4j to show the spring classes logs. The logs will show the order in which spring classes are called and also the request and response sent.

<logger name="org.springframework.ws" additivity="false">
   <level value="DEBUG#org.tiaa.infra.logging.TiaaLevel" />
   <appender-ref ref="DailyRollingFileAppender"/>
</logger>
夜清冷一曲。 2024-11-21 13:45:40

为@NeilStevens 解决方案+1...永远不会太晚!谢谢:-) 这里有一个轻微的重构,可以将内容打印到 sf4j 记录器并使用静态导入的魔力...:

import static SomeTestClass.ResponseOutputMatcher.printResponse;


public class SomeTestClass {
    private static final Logger LOG = LoggerFactory.getLogger(SomeTestClass.class);

    @Test
    public void someTest() {

        mockClient.sendRequest(...)
          .andExpect(printResponse(LOG))
          .andExpect(noFault());
    }

    @RequiredArgsConstructor
    public static class ResponseOutputMatcher implements ResponseMatcher {
        private final Logger logger;

        public ResponseOutputMatcher() {
            this(LoggerFactory.getLogger(ResponseOutputMatcher.class));
        }

        @Override
        public void match(WebServiceMessage request, WebServiceMessage response) throws IOException, AssertionError {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            response.writeTo(out);
            logger.info(format("Received payload response:\n%s\n%s\n%s", repeat(">", 80), out.toString(), repeat("_", 80)));
        }

        public static ResponseMatcher printResponse(Logger logger) {
            return new ResponseOutputMatcher(logger);
        }
    }

+1 for @NeilStevens solution... It's never too late!. Thanks :-) Here is a slight refactor to print stuff out to a sf4j logger and use the magic of static imports...:

import static SomeTestClass.ResponseOutputMatcher.printResponse;


public class SomeTestClass {
    private static final Logger LOG = LoggerFactory.getLogger(SomeTestClass.class);

    @Test
    public void someTest() {

        mockClient.sendRequest(...)
          .andExpect(printResponse(LOG))
          .andExpect(noFault());
    }

    @RequiredArgsConstructor
    public static class ResponseOutputMatcher implements ResponseMatcher {
        private final Logger logger;

        public ResponseOutputMatcher() {
            this(LoggerFactory.getLogger(ResponseOutputMatcher.class));
        }

        @Override
        public void match(WebServiceMessage request, WebServiceMessage response) throws IOException, AssertionError {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            response.writeTo(out);
            logger.info(format("Received payload response:\n%s\n%s\n%s", repeat(">", 80), out.toString(), repeat("_", 80)));
        }

        public static ResponseMatcher printResponse(Logger logger) {
            return new ResponseOutputMatcher(logger);
        }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文