/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ws.test.client;
import org.springframework.context.ApplicationContext;
import org.springframework.util.Assert;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.client.core.support.WebServiceGatewaySupport;
import org.springframework.ws.test.support.MockStrategiesHelper;
/**
* <strong>Main entry point for client-side Web service testing</strong>. Typically used to test a {@link
* WebServiceTemplate}, set up expectations on request messages, and create response messages.
*
* <p>The typical usage of this class is:
* <ol>
* <li>Create a {@code MockWebServiceServer} instance by calling {@link #createServer(WebServiceTemplate)},
* {@link #createServer(WebServiceGatewaySupport)}, or {@link #createServer(ApplicationContext)}.
* <li>Set up request expectations by calling {@link #expect(RequestMatcher)}, possibly by using the default
* {@link RequestMatcher} implementations provided in {@link RequestMatchers} (which can be statically imported).
* Multiple expectations can be set up by chaining {@link ResponseActions#andExpect(RequestMatcher)} calls.</li>
* <li>Create an appropriate response message by calling
* {@link ResponseActions#andRespond(ResponseCreator) andRespond(ResponseCreator)}, possibly by using the default
* {@link ResponseCreator} implementations provided in {@link ResponseCreators} (which can be statically imported).</li>
* <li>Use the {@code WebServiceTemplate} as normal, either directly of through client code.</li>
* <li>Call {@link #verify()}.</ol>
* Note that because of the 'fluent' API offered by this class (and related classes), you can typically use the Code
* Completion features (i.e. ctrl-space) in your IDE to set up the mocks.
*
* <p>For example:
* <blockquote><pre>
* import org.junit.*;
* import org.springframework.beans.factory.annotation.Autowired;
* import org.springframework.test.context.ContextConfiguration;
* import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
* import org.springframework.xml.transform.StringSource;
* <strong>import org.springframework.ws.test.client.MockWebServiceServer</strong>;
* <strong>import static org.springframework.ws.test.client.RequestMatchers.*</strong>;
* <strong>import static org.springframework.ws.test.client.ResponseCreators.*</strong>;
*
* @RunWith(SpringJUnit4ClassRunner.class)
* @ContextConfiguration("applicationContext.xml")
* public class MyWebServiceClientIntegrationTest {
*
* // MyWebServiceClient extends WebServiceGatewaySupport, and is configured in applicationContext.xml
* @Autowired
* private MyWebServiceClient client;
*
* private MockWebServiceServer mockServer;
*
* @Before
* public void createServer() throws Exception {
* <strong>mockServer = MockWebServiceServer.createServer(client)</strong>;
* }
*
* @Test
* public void getCustomerCount() throws Exception {
* Source expectedRequestPayload =
* new StringSource("<customerCountRequest xmlns=\"http://springframework.org/spring-ws/test\" />");
* Source responsePayload = new StringSource("<customerCountResponse xmlns='http://springframework.org/spring-ws/test'>" +
* "<customerCount>10</customerCount>" +
* "</customerCountResponse>");
*
* <strong>mockServer.expect(payload(expectedRequestPayload)).andRespond(withPayload(responsePayload));</strong>
*
* // client.getCustomerCount() uses the WebServiceTemplate
* int customerCount = client.getCustomerCount();
* assertEquals(10, response.getCustomerCount());
*
* <strong>mockServer.verify();</strong>
* }
* }
* </pre></blockquote>
*
* @author Arjen Poutsma
* @author Lukas Krecan
* @since 2.0
*/
public class MockWebServiceServer {
private final MockWebServiceMessageSender mockMessageSender;
private MockWebServiceServer(MockWebServiceMessageSender mockMessageSender) {
Assert.notNull(mockMessageSender, "'mockMessageSender' must not be null");
this.mockMessageSender = mockMessageSender;
}
/**
* Creates a {@code MockWebServiceServer} instance based on the given {@link WebServiceTemplate}.
*
* @param webServiceTemplate the web service template
* @return the created server
*/
public static MockWebServiceServer createServer(WebServiceTemplate webServiceTemplate) {
Assert.notNull(webServiceTemplate, "'webServiceTemplate' must not be null");
MockWebServiceMessageSender mockMessageSender = new MockWebServiceMessageSender();
webServiceTemplate.setMessageSender(mockMessageSender);
return new MockWebServiceServer(mockMessageSender);
}
/**
* Creates a {@code MockWebServiceServer} instance based on the given {@link WebServiceGatewaySupport}.
*
* @param gatewaySupport the client class
* @return the created server
*/
public static MockWebServiceServer createServer(WebServiceGatewaySupport gatewaySupport) {
Assert.notNull(gatewaySupport, "'gatewaySupport' must not be null");
return createServer(gatewaySupport.getWebServiceTemplate());
}
/**
* Creates a {@code MockWebServiceServer} instance based on the given {@link ApplicationContext}.
*
* <p>This factory method will try and find a configured {@link WebServiceTemplate} in the given application context.
* If no template can be found, it will try and find a {@link WebServiceGatewaySupport}, and use its configured
* template. If neither can be found, an exception is thrown.
*
* @param applicationContext the application context to base the client on
* @return the created server
* @throws IllegalArgumentException if the given application context contains neither a {@link WebServiceTemplate}
* nor a {@link WebServiceGatewaySupport}.
*/
public static MockWebServiceServer createServer(ApplicationContext applicationContext) {
MockStrategiesHelper strategiesHelper = new MockStrategiesHelper(applicationContext);
WebServiceTemplate webServiceTemplate = strategiesHelper.getStrategy(WebServiceTemplate.class);
if (webServiceTemplate != null) {
return createServer(webServiceTemplate);
}
WebServiceGatewaySupport gatewaySupport = strategiesHelper.getStrategy(WebServiceGatewaySupport.class);
if (gatewaySupport != null) {
return createServer(gatewaySupport);
}
throw new IllegalArgumentException(
"Could not find either WebServiceTemplate or WebServiceGatewaySupport in application context");
}
/**
* Records an expectation specified by the given {@link RequestMatcher}. Returns a {@link ResponseActions} object
* that allows for creating the response, or to set up more expectations.
*
* @param requestMatcher the request matcher expected
* @return the response actions
*/
public ResponseActions expect(RequestMatcher requestMatcher) {
MockSenderConnection connection = mockMessageSender.expectNewConnection();
connection.addRequestMatcher(requestMatcher);
return connection;
}
/**
* Verifies that all expectations were met.
*
* @throws AssertionError in case of unmet expectations
*/
public void verify() {
mockMessageSender.verifyConnections();
}
}