diff --git a/test/pom.xml b/test/pom.xml index 93c4e1f4..1feb256b 100644 --- a/test/pom.xml +++ b/test/pom.xml @@ -49,5 +49,9 @@ xmlunit compile + + org.springframework + spring-test + diff --git a/test/src/main/java/org/springframework/ws/mock/client2/DiffMatcher.java b/test/src/main/java/org/springframework/ws/mock/client2/DiffMatcher.java new file mode 100644 index 00000000..8eb06458 --- /dev/null +++ b/test/src/main/java/org/springframework/ws/mock/client2/DiffMatcher.java @@ -0,0 +1,60 @@ +/* + * 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.mock.client2; + +import java.io.IOException; +import java.net.URI; + +import org.springframework.ws.WebServiceMessage; +import org.springframework.xml.transform.TransformerObjectSupport; + +import org.custommonkey.xmlunit.Diff; + +import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual; +import static org.custommonkey.xmlunit.XMLAssert.fail; + +/** + * Implementation of {@link RequestMatcher} based on XMLUnit's {@link Diff}. + * + * @author Arjen Poutsma + * @since 2.0 + */ +abstract class DiffMatcher extends TransformerObjectSupport implements RequestMatcher { + + public final void match(URI uri, WebServiceMessage request) throws IOException, AssertionError { + try { + Diff diff = createDiff(request); + assertXMLEqual(diff, true); + } + catch (IOException ex) { + throw ex; + } + catch (Exception ex) { + fail("Could not create Diff: " + ex.getMessage()); + } + } + + /** + * Creates a {@link org.custommonkey.xmlunit.Diff} for the given request message. + * + * @param request the request message + * @return the diff + * @throws Exception in case of errors + */ + protected abstract Diff createDiff(WebServiceMessage request) throws Exception; + +} \ No newline at end of file diff --git a/test/src/main/java/org/springframework/ws/mock/client2/ErrorResponseCallback.java b/test/src/main/java/org/springframework/ws/mock/client2/ErrorResponseCallback.java new file mode 100644 index 00000000..66cd932c --- /dev/null +++ b/test/src/main/java/org/springframework/ws/mock/client2/ErrorResponseCallback.java @@ -0,0 +1,45 @@ +/* + * 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.mock.client2; + +import java.io.IOException; + +import org.springframework.ws.WebServiceMessage; + +/** + * Implementation of {@link ResponseCallback} that holds an error message. + * + * @author Arjen Poutsma + * @author Lukas Krecan + * @since 2.0 + */ +class ErrorResponseCallback implements ResponseCallback { + + private final String errorMessage; + + ErrorResponseCallback(String errorMessage) { + this.errorMessage = errorMessage; + } + + public void doWithResponse(WebServiceMessage response, WebServiceMessage request) throws IOException { + // Do nothing + } + + String getErrorMessage() { + return errorMessage; + } +} \ No newline at end of file diff --git a/test/src/main/java/org/springframework/ws/mock/client2/ExceptionResponseCallback.java b/test/src/main/java/org/springframework/ws/mock/client2/ExceptionResponseCallback.java new file mode 100644 index 00000000..a00c7548 --- /dev/null +++ b/test/src/main/java/org/springframework/ws/mock/client2/ExceptionResponseCallback.java @@ -0,0 +1,50 @@ +/* + * 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.mock.client2; + +import java.io.IOException; + +import org.springframework.ws.WebServiceMessage; + +/** + * Implementation of {@link ResponseCallback} that responds by throwing either an {@link IOException} or a {@link + * RuntimeException}. + * + * @author Arjen Poutsma + * @since 2.0 + */ +class ExceptionResponseCallback implements ResponseCallback { + + private final Exception exception; + + ExceptionResponseCallback(IOException exception) { + this.exception = exception; + } + + ExceptionResponseCallback(RuntimeException exception) { + this.exception = exception; + } + + public void doWithResponse(WebServiceMessage request, WebServiceMessage response) throws IOException { + if (exception instanceof IOException) { + throw (IOException) exception; + } + else { + throw (RuntimeException) exception; + } + } +} \ No newline at end of file diff --git a/test/src/main/java/org/springframework/ws/mock/client2/MockSenderConnection.java b/test/src/main/java/org/springframework/ws/mock/client2/MockSenderConnection.java new file mode 100644 index 00000000..950ab55c --- /dev/null +++ b/test/src/main/java/org/springframework/ws/mock/client2/MockSenderConnection.java @@ -0,0 +1,135 @@ +/* + * 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.mock.client2; + +import java.io.IOException; +import java.net.URI; +import java.util.LinkedList; +import java.util.List; + +import org.springframework.util.Assert; +import org.springframework.ws.WebServiceMessage; +import org.springframework.ws.WebServiceMessageFactory; +import org.springframework.ws.transport.FaultAwareWebServiceConnection; + +/** + * Mock implementation of {@link FaultAwareWebServiceConnection}. Implements {@link ResponseActions} to form a fluent + * API. + * + * @author Arjen Poutsma + * @author Lukas Krecan + * @since 2.0 + */ +class MockSenderConnection implements FaultAwareWebServiceConnection, ResponseActions { + + private final List requestMatchers = new LinkedList(); + + private URI uri; + + private boolean lastConnection = false; + + private WebServiceMessage request; + + private ResponseCallback responseCallback; + + void addRequestMatcher(RequestMatcher requestMatcher) { + Assert.notNull(requestMatcher, "'requestMatcher' must not be null"); + requestMatchers.add(requestMatcher); + } + + void setUri(URI uri) { + Assert.notNull(uri, "'uri' must not be null"); + this.uri = uri; + } + + void lastConnection() { + lastConnection = true; + } + + // ResponseActions implementation + + public ResponseActions andExpect(RequestMatcher requestMatcher) { + addRequestMatcher(requestMatcher); + return this; + } + + public void andRespond(ResponseCallback responseCallback) { + Assert.notNull(responseCallback, "'responseCallback' must not be null"); + this.responseCallback = responseCallback; + } + + // FaultAwareWebServiceConnection implementation + + public void send(WebServiceMessage message) throws IOException { + if (!requestMatchers.isEmpty()) { + for (RequestMatcher requestMatcher : requestMatchers) { + requestMatcher.match(uri, message); + } + } + else { + throw new AssertionError("Unexpected send() for [" + message + "]"); + } + this.request = message; + } + + public WebServiceMessage receive(WebServiceMessageFactory messageFactory) throws IOException { + if (responseCallback != null) { + WebServiceMessage response = messageFactory.createWebServiceMessage(); + responseCallback.doWithResponse(request, response); + return response; + } + else { + return null; + } + } + + public URI getUri() { + return uri; + } + + public boolean hasError() throws IOException { + return responseCallback instanceof ErrorResponseCallback; + } + + public String getErrorMessage() throws IOException { + if (responseCallback instanceof ErrorResponseCallback) { + return ((ErrorResponseCallback) responseCallback).getErrorMessage(); + } + else { + return null; + } + } + + public boolean hasFault() throws IOException { + return responseCallback instanceof SoapFaultResponseCallback; + } + + public void setFault(boolean fault) throws IOException { + // Do nothing + } + + public void close() throws IOException { + requestMatchers.clear(); + request = null; + responseCallback = null; + uri = null; + if (lastConnection) { + MockWebServiceMessageSenderHolder.clear(); + } + } + +} \ No newline at end of file diff --git a/test/src/main/java/org/springframework/ws/mock/client2/MockWebServiceMessageSender.java b/test/src/main/java/org/springframework/ws/mock/client2/MockWebServiceMessageSender.java new file mode 100644 index 00000000..742fb7ee --- /dev/null +++ b/test/src/main/java/org/springframework/ws/mock/client2/MockWebServiceMessageSender.java @@ -0,0 +1,62 @@ +/* + * 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.mock.client2; + +import java.io.IOException; +import java.net.URI; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import org.springframework.util.Assert; +import org.springframework.ws.transport.WebServiceMessageSender; + +import static org.junit.Assert.assertTrue; + +class MockWebServiceMessageSender implements WebServiceMessageSender { + + private final List expectedConnections = new LinkedList(); + + private Iterator connectionIterator; + + public MockSenderConnection createConnection(URI uri) throws IOException { + Assert.notNull(uri, "'uri' must not be null"); + if (connectionIterator == null) { + connectionIterator = expectedConnections.iterator(); + } + assertTrue("No further connections expected", connectionIterator.hasNext()); + + MockSenderConnection currentConnection = connectionIterator.next(); + currentConnection.setUri(uri); + if (!connectionIterator.hasNext()) { + currentConnection.lastConnection(); + } + return currentConnection; + } + + /** Always returns {@code true}. */ + public boolean supports(URI uri) { + return true; + } + + MockSenderConnection expectNewConnection() { + MockSenderConnection connection = new MockSenderConnection(); + expectedConnections.add(connection); + return connection; + } + +} \ No newline at end of file diff --git a/test/src/main/java/org/springframework/ws/mock/client2/MockWebServiceMessageSenderHolder.java b/test/src/main/java/org/springframework/ws/mock/client2/MockWebServiceMessageSenderHolder.java new file mode 100644 index 00000000..6fc99fa2 --- /dev/null +++ b/test/src/main/java/org/springframework/ws/mock/client2/MockWebServiceMessageSenderHolder.java @@ -0,0 +1,47 @@ +/* + * 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.mock.client2; + +import org.springframework.core.NamedThreadLocal; + +/** + * @author Arjen Poutsma + * @since 2.0 + */ +class MockWebServiceMessageSenderHolder { + + private static final NamedThreadLocal mockWebServiceMessageSenderHolder = + new NamedThreadLocal("Mock Message Sender"); + + /** Associate the given {@link MockWebServiceMessageSender} with the current thread. */ + public static void set(MockWebServiceMessageSender messageSender) { + mockWebServiceMessageSenderHolder.set(messageSender); + } + + /** Return the {@link MockWebServiceMessageSender} associated with the current thread, if any. */ + public static MockWebServiceMessageSender get() { + return mockWebServiceMessageSenderHolder.get(); + } + + /** + * Clears the holder. + */ + public static void clear() { + set(null); + } + +} diff --git a/test/src/main/java/org/springframework/ws/mock/client2/PayloadMatcher.java b/test/src/main/java/org/springframework/ws/mock/client2/PayloadMatcher.java new file mode 100644 index 00000000..aa8129b2 --- /dev/null +++ b/test/src/main/java/org/springframework/ws/mock/client2/PayloadMatcher.java @@ -0,0 +1,67 @@ +/* + * 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.mock.client2; + +import javax.xml.transform.Source; +import javax.xml.transform.TransformerException; +import javax.xml.transform.dom.DOMResult; + +import org.springframework.util.Assert; +import org.springframework.ws.WebServiceMessage; + +import org.custommonkey.xmlunit.Diff; +import org.w3c.dom.Document; + +import static junit.framework.Assert.fail; + +/** + * Matches {@link Source} payloads. + * + * @author Arjen Poutsma + * @author Lukas Krecan + * @since 2.0 + */ +class PayloadMatcher extends DiffMatcher { + + private final Source expected; + + PayloadMatcher(Source expected) { + Assert.notNull(expected, "'expected' must not be null"); + this.expected = expected; + } + + @Override + protected final Diff createDiff(WebServiceMessage request) throws Exception { + Source payload = request.getPayloadSource(); + if (payload == null) { + fail("Request message does not contain payload"); + } + return createDiff(payload); + } + + protected Diff createDiff(Source payload) throws TransformerException { + Document expectedDocument = createDocumentFromSource(expected); + Document actualDocument = createDocumentFromSource(payload); + return new Diff(expectedDocument, actualDocument); + } + + private Document createDocumentFromSource(Source source) throws TransformerException { + DOMResult result = new DOMResult(); + transform(source, result); + return (Document) result.getNode(); + } +} \ No newline at end of file diff --git a/test/src/main/java/org/springframework/ws/mock/client2/PayloadResponseCallback.java b/test/src/main/java/org/springframework/ws/mock/client2/PayloadResponseCallback.java new file mode 100644 index 00000000..0b4955e5 --- /dev/null +++ b/test/src/main/java/org/springframework/ws/mock/client2/PayloadResponseCallback.java @@ -0,0 +1,48 @@ +/* + * 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.mock.client2; + +import java.io.IOException; +import javax.xml.transform.Source; +import javax.xml.transform.TransformerException; + +import org.springframework.ws.WebServiceMessage; +import org.springframework.xml.transform.TransformerObjectSupport; + +/** + * Implementation of {@link ResponseCallback} that writes a {@link Source} response. + * + * @author Arjen Poutsma + * @since 2.0 + */ +class PayloadResponseCallback extends TransformerObjectSupport implements ResponseCallback { + + private final Source payload; + + PayloadResponseCallback(Source payload) { + this.payload = payload; + } + + public void doWithResponse(WebServiceMessage request, WebServiceMessage response) throws IOException { + try { + transform(payload, response.getPayloadResult()); + } + catch (TransformerException ex) { + throw new AssertionError("Could not transform response payload to message: " + ex.getMessage()); + } + } +} \ No newline at end of file diff --git a/test/src/main/java/org/springframework/ws/mock/client2/RequestMatcher.java b/test/src/main/java/org/springframework/ws/mock/client2/RequestMatcher.java new file mode 100644 index 00000000..e2bef32d --- /dev/null +++ b/test/src/main/java/org/springframework/ws/mock/client2/RequestMatcher.java @@ -0,0 +1,44 @@ +/* + * 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.mock.client2; + +import java.io.IOException; +import java.net.URI; + +import org.springframework.ws.WebServiceMessage; + +/** + * Defines the contract for matching requests to expectations. + * + * @author Arjen Poutsma + * @author Lukas Krecan + * @since 2.0 + */ +public interface RequestMatcher { + + /** + * Matches the given request message against the expectations. Implementations typically make use of JUnit-based + * assertions. + * + * @param uri the uri connected to + * @param request the request message to make assertions on + * @throws IOException in case of I/O errors + * @throws AssertionError if expectations are not met + */ + void match(URI uri, WebServiceMessage request) throws IOException, AssertionError; + +} \ No newline at end of file diff --git a/test/src/main/java/org/springframework/ws/mock/client2/ResponseActions.java b/test/src/main/java/org/springframework/ws/mock/client2/ResponseActions.java new file mode 100644 index 00000000..4e493786 --- /dev/null +++ b/test/src/main/java/org/springframework/ws/mock/client2/ResponseActions.java @@ -0,0 +1,41 @@ +/* + * 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.mock.client2; + +/** + * Allows for setting up responses. Implementations of this interface are returned by {@link WebServiceMock}. + * + * @author Arjen Poutsma + * @author Lukas Krecan + * @since 2.0 + */ +public interface ResponseActions { + /** + * Allows for further expectations to be set on the request. + * + * @return the request expectations + */ + ResponseActions andExpect(RequestMatcher requestMatcher); + + /** + * Sets the {@link ResponseCallback} for this mock. + * + * @param responseCallback the response callback + */ + void andRespond(ResponseCallback responseCallback); + +} \ No newline at end of file diff --git a/test/src/main/java/org/springframework/ws/mock/client2/ResponseCallback.java b/test/src/main/java/org/springframework/ws/mock/client2/ResponseCallback.java new file mode 100644 index 00000000..54f5396b --- /dev/null +++ b/test/src/main/java/org/springframework/ws/mock/client2/ResponseCallback.java @@ -0,0 +1,42 @@ +/* + * 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.mock.client2; + +import java.io.IOException; + +import org.springframework.ws.WebServiceMessage; + +/** + * Callback interface for code that operates on response {@link org.springframework.ws.WebServiceMessage}s. Defines the contract for creating + * responses in test scenarios. + * + * @author Arjen Poutsma + * @author Lukas Krecan + * @since 2.0 + */ +public interface ResponseCallback { + + /** + * Execute any number of operations on the supplied response, given the request. + * + * @param request the request message + * @param response the response message + * @throws java.io.IOException in case of I/O errors + */ + void doWithResponse(WebServiceMessage request, WebServiceMessage response) throws IOException; + +} \ No newline at end of file diff --git a/test/src/main/java/org/springframework/ws/mock/client2/SoapFaultResponseCallback.java b/test/src/main/java/org/springframework/ws/mock/client2/SoapFaultResponseCallback.java new file mode 100644 index 00000000..4ce4bb2f --- /dev/null +++ b/test/src/main/java/org/springframework/ws/mock/client2/SoapFaultResponseCallback.java @@ -0,0 +1,95 @@ +/* + * 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.mock.client2; + +import java.io.IOException; +import java.util.Locale; + +import org.springframework.ws.WebServiceMessage; +import org.springframework.ws.soap.SoapBody; +import org.springframework.ws.soap.SoapMessage; + +import static org.junit.Assert.fail; + +/** + * Implementation of {@link ResponseCallback} that responds with a SOAP fault. + * + * @author Arjen Poutsma + * @since 2.0 + */ +abstract class SoapFaultResponseCallback implements ResponseCallback { + + public final void doWithResponse(WebServiceMessage request, WebServiceMessage response) throws IOException { + if (!(response instanceof SoapMessage)) { + fail("Response message is not a SOAP message"); + return; + } + SoapMessage soapResponse = (SoapMessage) response; + SoapBody soapResponseBody = soapResponse.getSoapBody(); + if (soapResponseBody == null) { + fail("SOAP message [" + soapResponse + "] does not contain SOAP body"); + } + addSoapFault(soapResponseBody); + } + + public abstract void addSoapFault(SoapBody soapBody); + + public static SoapFaultResponseCallback createMustUnderstandFault(final String faultStringOrReason, + final Locale locale) { + return new SoapFaultResponseCallback() { + @Override + public void addSoapFault(SoapBody soapBody) { + soapBody.addMustUnderstandFault(faultStringOrReason, locale); + } + }; + + } + + public static SoapFaultResponseCallback createClientOrSenderFault(final String faultStringOrReason, + final Locale locale) { + return new SoapFaultResponseCallback() { + @Override + public void addSoapFault(SoapBody soapBody) { + soapBody.addClientOrSenderFault(faultStringOrReason, locale); + } + }; + } + + public static SoapFaultResponseCallback createServerOrReceiverFault(final String faultStringOrReason, + final Locale locale) { + return new SoapFaultResponseCallback() { + @Override + public void addSoapFault(SoapBody soapBody) { + soapBody.addServerOrReceiverFault(faultStringOrReason, locale); + } + }; + + } + + public static SoapFaultResponseCallback createVersionMismatchFault(final String faultStringOrReason, + final Locale locale) { + return new SoapFaultResponseCallback() { + @Override + public void addSoapFault(SoapBody soapBody) { + soapBody.addVersionMismatchFault(faultStringOrReason, locale); + } + }; + + } + + +} \ No newline at end of file diff --git a/test/src/main/java/org/springframework/ws/mock/client2/SoapHeaderMatcher.java b/test/src/main/java/org/springframework/ws/mock/client2/SoapHeaderMatcher.java new file mode 100644 index 00000000..6c6d1002 --- /dev/null +++ b/test/src/main/java/org/springframework/ws/mock/client2/SoapHeaderMatcher.java @@ -0,0 +1,67 @@ +/* + * 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.mock.client2; + +import java.io.IOException; +import java.net.URI; +import java.util.Iterator; +import javax.xml.namespace.QName; + +import org.springframework.ws.WebServiceMessage; +import org.springframework.ws.soap.SoapHeader; +import org.springframework.ws.soap.SoapHeaderElement; +import org.springframework.ws.soap.SoapMessage; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +/** + * Matches SOAP headers. + * + * @author Arjen Poutsma + * @since 2.0 + */ +class SoapHeaderMatcher implements RequestMatcher { + + private final QName soapHeaderName; + + SoapHeaderMatcher(QName soapHeaderName) { + this.soapHeaderName = soapHeaderName; + } + + public void match(URI uri, WebServiceMessage request) throws IOException, AssertionError { + if (!(request instanceof SoapMessage)) { + fail("Request message is not a SOAP message"); + return; + } + SoapMessage soapMessage = (SoapMessage) request; + SoapHeader soapHeader = soapMessage.getSoapHeader(); + if (soapHeader == null) { + fail("SOAP message [" + soapMessage + "] does not contain SOAP header"); + } + Iterator soapHeaderElementIterator = soapHeader.examineAllHeaderElements(); + boolean found = false; + while (soapHeaderElementIterator.hasNext()) { + SoapHeaderElement soapHeaderElement = soapHeaderElementIterator.next(); + if (soapHeaderName.equals(soapHeaderElement.getName())) { + found = true; + break; + } + } + assertTrue("SOAP header [" + soapHeaderName + "] not found", found); + } +} \ No newline at end of file diff --git a/test/src/main/java/org/springframework/ws/mock/client2/UriMatcher.java b/test/src/main/java/org/springframework/ws/mock/client2/UriMatcher.java new file mode 100644 index 00000000..684bb3de --- /dev/null +++ b/test/src/main/java/org/springframework/ws/mock/client2/UriMatcher.java @@ -0,0 +1,42 @@ +/* + * 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.mock.client2; + +import java.net.URI; + +import org.springframework.ws.WebServiceMessage; + +import static org.junit.Assert.assertEquals; + +/** + * Matches {@link URI}s. + * + * @author Arjen Poutsma + * @since 2.0 + */ +class UriMatcher implements RequestMatcher { + + private final URI expected; + + UriMatcher(URI expected) { + this.expected = expected; + } + + public void match(URI actual, WebServiceMessage request) { + assertEquals("Unexpected connection", expected, actual); + } +} diff --git a/test/src/main/java/org/springframework/ws/mock/client2/WebServiceMock.java b/test/src/main/java/org/springframework/ws/mock/client2/WebServiceMock.java new file mode 100644 index 00000000..8a3b618e --- /dev/null +++ b/test/src/main/java/org/springframework/ws/mock/client2/WebServiceMock.java @@ -0,0 +1,259 @@ +/* + * 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.mock.client2; + +import java.io.IOException; +import java.net.URI; +import java.util.Locale; +import javax.xml.namespace.QName; +import javax.xml.transform.Source; + +import org.springframework.core.io.Resource; +import org.springframework.util.Assert; +import org.springframework.ws.client.core.WebServiceTemplate; +import org.springframework.xml.transform.ResourceSource; +import org.springframework.xml.transform.StringSource; + +/** + * @author Arjen Poutsma + * @author Lukas Krecan + * @since 2.0 + */ +public abstract class WebServiceMock { + + public static void mockWebServiceTemplate(WebServiceTemplate webServiceTemplate) { + Assert.notNull(webServiceTemplate, "'webServiceTemplate' must not be null"); + + MockWebServiceMessageSender mockMessageSender = new MockWebServiceMessageSender(); + webServiceTemplate.setMessageSender(mockMessageSender); + MockWebServiceMessageSenderHolder.set(mockMessageSender); + } + + /** + * Records an expectation specified by the given {@link RequestMatcher}. Returns a {@link ResponseActions} object + * that allows for setting up the response, or more expectations. + * + * @param requestMatcher the request matcher expected + * @return the response actions + */ + public static ResponseActions expect(RequestMatcher requestMatcher) { + MockWebServiceMessageSender messageSender = MockWebServiceMessageSenderHolder.get(); + Assert.state(messageSender != null, + "WebServiceTemplate has not been mocked. Did you call mockWebServiceTemplate() ?"); + + MockSenderConnection connection = messageSender.expectNewConnection(); + connection.addRequestMatcher(requestMatcher); + return connection; + } + + // RequestMatchers + + /** + * Expects the given String XML payload. + * + * @param payload the XML payload + * @return the request matcher + */ + public static RequestMatcher payload(String payload) { + Assert.notNull(payload, "'payload' must not be null"); + return new PayloadMatcher(new StringSource(payload)); + } + + /** + * Expects the given {@link Source} XML payload. + * + * @param payload the XML payload + * @return the request matcher + */ + public static RequestMatcher payload(Source payload) { + Assert.notNull(payload, "'payload' must not be null"); + return new PayloadMatcher(payload); + } + + /** + * Expects the given {@link Resource} XML payload. + * + * @param payload the XML payload + * @return the request matcher + */ + public static RequestMatcher payload(Resource payload) { + Assert.notNull(payload, "'payload' must not be null"); + return new PayloadMatcher(createResourceSource(payload)); + } + + /** + * Expects the given SOAP header in the outgoing message. + * + * @param soapHeaderName the qualified name of the SOAP header to expect + * @return the request matcher + */ + public static RequestMatcher soapHeader(QName soapHeaderName) { + Assert.notNull(soapHeaderName, "'soapHeaderName' must not be null"); + return new SoapHeaderMatcher(soapHeaderName); + } + + /** + * Expects a connection to the given URI. + * + * @param uri the String uri expected to connect to + * @return the request matcher + */ + public static RequestMatcher connectionTo(String uri) { + Assert.notNull(uri, "'uri' must not be null"); + return connectionTo(URI.create(uri)); + } + + /** + * Expects a connection to the given URI. + * + * @param uri the String uri expected to connect to + * @return the request matcher + */ + public static RequestMatcher connectionTo(URI uri) { + Assert.notNull(uri, "'uri' must not be null"); + return new UriMatcher(uri); + } + + // ResponseCallbacks + + /** + * Respond with the given String XML as payload response. + * + * @param payload the response payload + * @return the response callback + */ + public static ResponseCallback withPayload(String payload) { + Assert.notNull(payload, "'payload' must not be null"); + return new PayloadResponseCallback(new StringSource(payload)); + } + + /** + * Respond with the given {@link Source} XML as payload response. + * + * @param payload the response payload + * @return the response callback + */ + public static ResponseCallback withPayload(Source payload) { + Assert.notNull(payload, "'payload' must not be null"); + return new PayloadResponseCallback(payload); + } + + /** + * Respond with the given {@link Resource} XML as payload response. + * + * @param payload the response payload + * @return the response callback + */ + public static ResponseCallback withPayload(Resource payload) { + Assert.notNull(payload, "'payload' must not be null"); + return new PayloadResponseCallback(createResourceSource(payload)); + } + + /** + * Respond with an error. + * + * @param errorMessage the error message + * @return the response callback + * @see org.springframework.ws.transport.WebServiceConnection#hasError() + * @see org.springframework.ws.transport.WebServiceConnection#getErrorMessage() + */ + public static ResponseCallback withError(String errorMessage) { + Assert.hasLength(errorMessage, "'errorMessage' must not be empty"); + return new ErrorResponseCallback(errorMessage); + } + + /** + * Respond with an {@link IOException}. + * + * @param ioException the exception to be thrown + * @return the response callback + */ + public static ResponseCallback withException(IOException ioException) { + Assert.notNull(ioException, "'ioException' must not be null"); + return new ExceptionResponseCallback(ioException); + } + + /** + * Respond with an {@link RuntimeException}. + * + * @param ex the runtime exception to be thrown + * @return the response callback + */ + public static ResponseCallback withException(RuntimeException ex) { + Assert.notNull(ex, "'ex' must not be null"); + return new ExceptionResponseCallback(ex); + } + + /** + * Respond with a {@code MustUnderstand} fault. + * + * @param faultStringOrReason the SOAP 1.1 fault string or SOAP 1.2 reason text + * @param locale the language of faultStringOrReason. Optional for SOAP 1.1 + * @see org.springframework.ws.soap.SoapBody#addMustUnderstandFault(String, Locale) + */ + public static ResponseCallback withMustUnderstandFault(String faultStringOrReason, Locale locale) { + Assert.hasLength(faultStringOrReason, "'faultStringOrReason' must not be empty"); + return SoapFaultResponseCallback.createMustUnderstandFault(faultStringOrReason, locale); + } + /** + * Respond with a {@code Client} (SOAP 1.1) or {@code Sender} (SOAP 1.2) fault. + * + * @param faultStringOrReason the SOAP 1.1 fault string or SOAP 1.2 reason text + * @param locale the language of faultStringOrReason. Optional for SOAP 1.1 + * @see org.springframework.ws.soap.SoapBody#addClientOrSenderFault(String, Locale) + */ + public static ResponseCallback withClientOrSenderFault(String faultStringOrReason, Locale locale) { + Assert.hasLength(faultStringOrReason, "'faultStringOrReason' must not be empty"); + return SoapFaultResponseCallback.createClientOrSenderFault(faultStringOrReason, locale); + } + + /** + * Respond with a {@code Server} (SOAP 1.1) or {@code Receiver} (SOAP 1.2) fault. + * + * @param faultStringOrReason the SOAP 1.1 fault string or SOAP 1.2 reason text + * @param locale the language of faultStringOrReason. Optional for SOAP 1.1 + * @see org.springframework.ws.soap.SoapBody#addServerOrReceiverFault(String, Locale) + */ + public static ResponseCallback withServerOrReceiverFault(String faultStringOrReason, Locale locale) { + Assert.hasLength(faultStringOrReason, "'faultStringOrReason' must not be empty"); + return SoapFaultResponseCallback.createServerOrReceiverFault(faultStringOrReason, locale); + } + + /** + * Respond with a {@code VersionMismatch} fault. + * + * @param faultStringOrReason the SOAP 1.1 fault string or SOAP 1.2 reason text + * @param locale the language of faultStringOrReason. Optional for SOAP 1.1 + * @see org.springframework.ws.soap.SoapBody#addVersionMismatchFault(String, Locale) + */ + public static ResponseCallback withVersionMismatchFault(String faultStringOrReason, Locale locale) { + Assert.hasLength(faultStringOrReason, "'faultStringOrReason' must not be empty"); + return SoapFaultResponseCallback.createVersionMismatchFault(faultStringOrReason, locale); + } + + + private static ResourceSource createResourceSource(Resource resource) { + try { + return new ResourceSource(resource); + } + catch (IOException ex) { + throw new IllegalArgumentException(resource + " could not be opened", ex); + } + } + + +} diff --git a/test/src/test/java/org/springframework/ws/mock/client2/ExceptionResponseCallbackTest.java b/test/src/test/java/org/springframework/ws/mock/client2/ExceptionResponseCallbackTest.java new file mode 100644 index 00000000..d141039c --- /dev/null +++ b/test/src/test/java/org/springframework/ws/mock/client2/ExceptionResponseCallbackTest.java @@ -0,0 +1,38 @@ +/* + * 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.mock.client2; + +import java.io.IOException; + +import org.junit.Test; + +public class ExceptionResponseCallbackTest { + + @Test(expected = IOException.class) + public void ioException() throws Exception { + ExceptionResponseCallback callback = new ExceptionResponseCallback(new IOException()); + + callback.doWithResponse(null, null); + } + + @Test(expected = RuntimeException.class) + public void runtimeException() throws Exception { + ExceptionResponseCallback callback = new ExceptionResponseCallback(new RuntimeException()); + + callback.doWithResponse(null, null); + } +} \ No newline at end of file diff --git a/test/src/test/java/org/springframework/ws/mock/client2/PayloadMatcherTest.java b/test/src/test/java/org/springframework/ws/mock/client2/PayloadMatcherTest.java new file mode 100644 index 00000000..8ac77af4 --- /dev/null +++ b/test/src/test/java/org/springframework/ws/mock/client2/PayloadMatcherTest.java @@ -0,0 +1,53 @@ +/* + * 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.mock.client2; + +import org.springframework.ws.WebServiceMessage; +import org.springframework.xml.transform.StringSource; + +import org.junit.Test; + +import static org.easymock.EasyMock.*; + +public class PayloadMatcherTest { + + @Test + public void match() throws Exception { + String xml = ""; + WebServiceMessage message = createMock(WebServiceMessage.class); + expect(message.getPayloadSource()).andReturn(new StringSource(xml)); + replay(message); + + PayloadMatcher matcher = new PayloadMatcher(new StringSource(xml)); + matcher.match(null, message); + + verify(message); + } + + @Test(expected = AssertionError.class) + public void nonMatch() throws Exception { + String actual = ""; + WebServiceMessage message = createMock(WebServiceMessage.class); + expect(message.getPayloadSource()).andReturn(new StringSource(actual)); + replay(message); + + String expected = ""; + PayloadMatcher matcher = new PayloadMatcher(new StringSource(expected)); + matcher.match(null, message); + } + +} \ No newline at end of file diff --git a/test/src/test/java/org/springframework/ws/mock/client2/SoapFaultResponseCallbackTest.java b/test/src/test/java/org/springframework/ws/mock/client2/SoapFaultResponseCallbackTest.java new file mode 100644 index 00000000..181de95e --- /dev/null +++ b/test/src/test/java/org/springframework/ws/mock/client2/SoapFaultResponseCallbackTest.java @@ -0,0 +1,107 @@ +/* + * 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.mock.client2; + +import java.io.IOException; +import java.util.Locale; +import javax.xml.soap.MessageFactory; +import javax.xml.soap.SOAPException; +import javax.xml.soap.SOAPMessage; + +import org.springframework.ws.soap.SoapMessage; +import org.springframework.ws.soap.SoapVersion; +import org.springframework.ws.soap.saaj.SaajSoapMessage; +import org.springframework.ws.soap.soap11.Soap11Fault; + +import org.junit.Before; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class SoapFaultResponseCallbackTest { + + private SoapMessage response; + + @Before + public void createResponse() throws SOAPException { + MessageFactory messageFactory = MessageFactory.newInstance(); + SOAPMessage saajResponse = messageFactory.createMessage(); + this.response = new SaajSoapMessage(saajResponse); + } + + @Test + public void clientOrSenderFault() throws IOException { + String faultString = "Foo"; + SoapFaultResponseCallback callback = SoapFaultResponseCallback.createClientOrSenderFault(faultString, Locale.ENGLISH); + + callback.doWithResponse(null, response); + + assertTrue("Response has no fault", response.hasFault()); + Soap11Fault soapFault = (Soap11Fault) response.getSoapBody().getFault(); + assertEquals("Response has invalid fault code", SoapVersion.SOAP_11.getClientOrSenderFaultName(), + soapFault.getFaultCode()); + assertEquals("Response has invalid fault string", faultString, soapFault.getFaultStringOrReason()); + assertEquals("Response has invalid fault locale", Locale.ENGLISH, soapFault.getFaultStringLocale()); + } + + @Test + public void mustUnderstandFault() throws IOException { + String faultString = "Foo"; + SoapFaultResponseCallback callback = SoapFaultResponseCallback.createMustUnderstandFault(faultString, Locale.ENGLISH); + + callback.doWithResponse(null, response); + + assertTrue("Response has no fault", response.hasFault()); + Soap11Fault soapFault = (Soap11Fault) response.getSoapBody().getFault(); + assertEquals("Response has invalid fault code", SoapVersion.SOAP_11.getMustUnderstandFaultName(), + soapFault.getFaultCode()); + assertEquals("Response has invalid fault string", faultString, soapFault.getFaultStringOrReason()); + assertEquals("Response has invalid fault locale", Locale.ENGLISH, soapFault.getFaultStringLocale()); + } + + @Test + public void serverOrReceiverFault() throws IOException { + String faultString = "Foo"; + SoapFaultResponseCallback callback = SoapFaultResponseCallback.createServerOrReceiverFault(faultString, Locale.ENGLISH); + + callback.doWithResponse(null, response); + + assertTrue("Response has no fault", response.hasFault()); + Soap11Fault soapFault = (Soap11Fault) response.getSoapBody().getFault(); + assertEquals("Response has invalid fault code", SoapVersion.SOAP_11.getServerOrReceiverFaultName(), + soapFault.getFaultCode()); + assertEquals("Response has invalid fault string", faultString, soapFault.getFaultStringOrReason()); + assertEquals("Response has invalid fault locale", Locale.ENGLISH, soapFault.getFaultStringLocale()); + } + + @Test + public void versionMismatchFault() throws IOException { + String faultString = "Foo"; + SoapFaultResponseCallback callback = SoapFaultResponseCallback.createVersionMismatchFault(faultString, Locale.ENGLISH); + + callback.doWithResponse(null, response); + + assertTrue("Response has no fault", response.hasFault()); + Soap11Fault soapFault = (Soap11Fault) response.getSoapBody().getFault(); + assertEquals("Response has invalid fault code", SoapVersion.SOAP_11.getVersionMismatchFaultName(), + soapFault.getFaultCode()); + assertEquals("Response has invalid fault string", faultString, soapFault.getFaultStringOrReason()); + assertEquals("Response has invalid fault locale", Locale.ENGLISH, soapFault.getFaultStringLocale()); + } + +} diff --git a/test/src/test/java/org/springframework/ws/mock/client2/SoapHeaderMatcherTest.java b/test/src/test/java/org/springframework/ws/mock/client2/SoapHeaderMatcherTest.java new file mode 100644 index 00000000..6ba66c2f --- /dev/null +++ b/test/src/test/java/org/springframework/ws/mock/client2/SoapHeaderMatcherTest.java @@ -0,0 +1,70 @@ +/* + * 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.mock.client2; + +import javax.xml.namespace.QName; +import javax.xml.soap.MessageFactory; +import javax.xml.soap.SOAPMessage; + +import org.springframework.ws.WebServiceMessage; +import org.springframework.ws.soap.SoapMessage; +import org.springframework.ws.soap.saaj.SaajSoapMessage; + +import org.junit.Before; +import org.junit.Test; + +import static org.easymock.EasyMock.createMock; + +public class SoapHeaderMatcherTest { + + private SoapHeaderMatcher matcher; + + private QName expectedHeaderName; + + @Before + public void setUp() throws Exception { + expectedHeaderName = new QName("http://example.com", "header"); + matcher = new SoapHeaderMatcher(expectedHeaderName); + } + + @Test + public void match() throws Exception { + MessageFactory messageFactory = MessageFactory.newInstance(); + SOAPMessage saajMessage = messageFactory.createMessage(); + saajMessage.getSOAPHeader().addHeaderElement(expectedHeaderName); + SoapMessage soapMessage = new SaajSoapMessage(saajMessage); + + matcher.match(null, soapMessage); + } + + @Test(expected = AssertionError.class) + public void nonMatch() throws Exception { + MessageFactory messageFactory = MessageFactory.newInstance(); + SOAPMessage saajMessage = messageFactory.createMessage(); + SoapMessage soapMessage = new SaajSoapMessage(saajMessage); + + matcher.match(null, soapMessage); + } + + @Test(expected = AssertionError.class) + public void nonSoap() throws Exception { + WebServiceMessage message = createMock(WebServiceMessage.class); + + matcher.match(null, message); + } + +} \ No newline at end of file diff --git a/test/src/test/java/org/springframework/ws/mock/client2/WebServiceMockTest.java b/test/src/test/java/org/springframework/ws/mock/client2/WebServiceMockTest.java new file mode 100644 index 00000000..c487786d --- /dev/null +++ b/test/src/test/java/org/springframework/ws/mock/client2/WebServiceMockTest.java @@ -0,0 +1,158 @@ +/* + * 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.mock.client2; + +import java.io.IOException; +import java.net.URI; +import javax.xml.namespace.QName; +import javax.xml.transform.TransformerException; + +import org.springframework.ws.WebServiceMessage; +import org.springframework.ws.client.core.WebServiceMessageCallback; +import org.springframework.ws.client.core.WebServiceTemplate; +import org.springframework.ws.soap.SoapMessage; +import org.springframework.ws.soap.saaj.SaajSoapMessage; +import org.springframework.xml.transform.StringResult; +import org.springframework.xml.transform.StringSource; + +import org.easymock.EasyMock; +import org.junit.Before; +import org.junit.Test; + +import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.springframework.ws.mock.client2.WebServiceMock.*; + +public class WebServiceMockTest { + + private WebServiceTemplate template; + + @Before + public void setUp() throws Exception { + template = new WebServiceTemplate(); + template.setDefaultUri("http://example.com"); + + mockWebServiceTemplate(template); + } + + @Test + public void mocks() throws Exception { + String uri = "http://example.com"; + + RequestMatcher requestMatcher1 = EasyMock.createStrictMock("requestMatcher1", RequestMatcher.class); + RequestMatcher requestMatcher2 = EasyMock.createStrictMock("requestMatcher2", RequestMatcher.class); + ResponseCallback responseCallback = EasyMock.createStrictMock(ResponseCallback.class); + + requestMatcher1.match(EasyMock.eq(URI.create(uri)), EasyMock.isA(SaajSoapMessage.class)); + requestMatcher2.match(EasyMock.eq(URI.create(uri)), EasyMock.isA(SaajSoapMessage.class)); + responseCallback.doWithResponse(EasyMock.isA(SaajSoapMessage.class), EasyMock.isA(SaajSoapMessage.class)); + + EasyMock.replay(requestMatcher1, requestMatcher2, responseCallback); + + expect(requestMatcher1).andExpect(requestMatcher2).andRespond(responseCallback); + template.sendSourceAndReceiveToResult(uri, new StringSource(""), + new StringResult()); + + EasyMock.verify(requestMatcher1, requestMatcher2, responseCallback); + } + + @Test + public void payloadMatch() throws Exception { + String request = ""; + String response = ""; + + expect(payload(request)).andRespond(withPayload(response)); + + StringResult result = new StringResult(); + template.sendSourceAndReceiveToResult(new StringSource(request), result); + assertXMLEqual(result.toString(), response); + } + + @Test(expected = AssertionError.class) + public void payloadNonMatch() throws Exception { + String expected = ""; + + expect(payload(expected)); + + StringResult result = new StringResult(); + String actual = ""; + template.sendSourceAndReceiveToResult(new StringSource(actual), result); + } + + @Test + public void soapHeaderMatch() throws Exception { + final QName soapHeaderName = new QName("http://example.com", "mySoapHeader"); + + expect(soapHeader(soapHeaderName)); + + template.sendSourceAndReceiveToResult(new StringSource(""), + new WebServiceMessageCallback() { + public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException { + SoapMessage soapMessage = (SoapMessage) message; + soapMessage.getSoapHeader().addHeaderElement(soapHeaderName); + } + }, new StringResult()); + } + + @Test(expected = AssertionError.class) + public void soapHeaderNonMatch() throws Exception { + QName soapHeaderName = new QName("http://example.com", "mySoapHeader"); + + expect(soapHeader(soapHeaderName)); + + template.sendSourceAndReceiveToResult(new StringSource(""), + new StringResult()); + } + + @Test + public void connectionMatch() throws Exception { + String uri = "http://example.com"; + expect(connectionTo(uri)); + + template.sendSourceAndReceiveToResult(uri, new StringSource(""), + new StringResult()); + } + + @Test(expected = AssertionError.class) + public void connectionNonMatch() throws Exception { + String expected = "http://expected.com"; + expect(connectionTo(expected)); + + String actual = "http://actual.com"; + template.sendSourceAndReceiveToResult(actual, new StringSource(""), + new StringResult()); + } + + @Test + public void verifyThreadLocalCleanUp() throws Exception { + String request = ""; + String response = ""; + + expect(payload(request)).andRespond(withPayload(response)); + expect(payload(request)).andRespond(withPayload(response)); + assertNotNull(MockWebServiceMessageSenderHolder.get()); + + template.sendSourceAndReceiveToResult(new StringSource(request), new StringResult()); + assertNotNull(MockWebServiceMessageSenderHolder.get()); + + template.sendSourceAndReceiveToResult(new StringSource(request), new StringResult()); + assertNull(MockWebServiceMessageSenderHolder.get()); + } + + +} diff --git a/test/src/test/java/org/springframework/ws/mock/client2/integration/IntegrationTest.java b/test/src/test/java/org/springframework/ws/mock/client2/integration/IntegrationTest.java new file mode 100644 index 00000000..7d362be5 --- /dev/null +++ b/test/src/test/java/org/springframework/ws/mock/client2/integration/IntegrationTest.java @@ -0,0 +1,67 @@ +/* + * 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.mock.client2.integration; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.ws.client.core.WebServiceTemplate; +import org.springframework.ws.mock.client.CustomerCountRequest; +import org.springframework.ws.mock.client.CustomerCountResponse; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.assertEquals; +import static org.springframework.ws.mock.client2.WebServiceMock.*; + +/** + * Integration test for client-side WebService testing. In different package so we can't use the package-protected + * classes. + * + * @author Arjen Poutsma + */ +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("integration-test.xml") +public class IntegrationTest { + + @Autowired + private WebServiceTemplate webServiceTemplate; + + @Before + public void setUpMocks() throws Exception { + mockWebServiceTemplate(webServiceTemplate); + } + + @Test + public void basic() throws Exception { + String expectedRequestPayload = "" + + "John Doe" + ""; + String responsePayload = "" + + "10" + ""; + + expect(payload(expectedRequestPayload)).andRespond(withPayload(responsePayload)); + + CustomerCountRequest request = new CustomerCountRequest(); + request.setCustomerName("John Doe"); + + CustomerCountResponse response = (CustomerCountResponse) webServiceTemplate.marshalSendAndReceive(request); + assertEquals(10, response.getCustomerCount()); + } + +} diff --git a/test/src/test/resources/org/springframework/ws/mock/client2/integration/integration-test.xml b/test/src/test/resources/org/springframework/ws/mock/client2/integration/integration-test.xml new file mode 100644 index 00000000..7f11c52b --- /dev/null +++ b/test/src/test/resources/org/springframework/ws/mock/client2/integration/integration-test.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + org.springframework.ws.mock.client.CustomerCountRequest + org.springframework.ws.mock.client.CustomerCountResponse + + + + + \ No newline at end of file