SWS-544 - Added XPath validation
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* 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.client;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.dom.DOMResult;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.ws.WebServiceMessage;
|
||||
import org.springframework.xml.transform.TransformerObjectSupport;
|
||||
import org.springframework.xml.xpath.XPathExpression;
|
||||
import org.springframework.xml.xpath.XPathExpressionFactory;
|
||||
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import static org.springframework.ws.mock.client.Assert.assertEquals;
|
||||
import static org.springframework.ws.mock.client.Assert.fail;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link XPathExpectations}.
|
||||
*
|
||||
* @author Lukas Krecan
|
||||
* @author Arjen Poutsma
|
||||
* @since 2.0
|
||||
*/
|
||||
class DefaultXPathExpectations extends TransformerObjectSupport implements XPathExpectations {
|
||||
|
||||
private final XPathExpression expression;
|
||||
|
||||
private final String expressionString;
|
||||
|
||||
DefaultXPathExpectations(String expression, Map<String, String> namespaces) {
|
||||
Assert.hasLength(expression, "'expression' must not be empty");
|
||||
this.expression = XPathExpressionFactory.createXPathExpression(expression, namespaces);
|
||||
this.expressionString = expression;
|
||||
}
|
||||
|
||||
public RequestMatcher exists() {
|
||||
return new RequestMatcher() {
|
||||
public void match(URI uri, WebServiceMessage request) throws IOException, AssertionError {
|
||||
Node payload = transformToNode(request);
|
||||
Node result = expression.evaluateAsNode(payload);
|
||||
if (result == null) {
|
||||
fail("No match for \"" + expressionString + "\" found");
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public RequestMatcher doesNotExist() {
|
||||
return new RequestMatcher() {
|
||||
public void match(URI uri, WebServiceMessage request) throws IOException, AssertionError {
|
||||
Node payload = transformToNode(request);
|
||||
Node result = expression.evaluateAsNode(payload);
|
||||
if (result != null) {
|
||||
fail("Match for \"" + expressionString + "\" found");
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public RequestMatcher evaluatesTo(final boolean expectedValue) {
|
||||
return new RequestMatcher() {
|
||||
public void match(URI uri, WebServiceMessage request) throws IOException, AssertionError {
|
||||
Node payload = transformToNode(request);
|
||||
boolean result = expression.evaluateAsBoolean(payload);
|
||||
assertEquals("Evaluation of XPath expression \"" + expressionString + "\" failed.", expectedValue,
|
||||
result);
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public RequestMatcher evaluatesTo(int expectedValue) {
|
||||
return evaluatesTo((double) expectedValue);
|
||||
}
|
||||
|
||||
public RequestMatcher evaluatesTo(final double expectedValue) {
|
||||
return new RequestMatcher() {
|
||||
public void match(URI uri, WebServiceMessage request) throws IOException, AssertionError {
|
||||
Node payload = transformToNode(request);
|
||||
double result = expression.evaluateAsNumber(payload);
|
||||
assertEquals("Evaluation of XPath expression \"" + expressionString + "\" failed.", expectedValue,
|
||||
result);
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public RequestMatcher evaluatesTo(final String expectedValue) {
|
||||
Assert.notNull(expectedValue, "'expectedValue' must not be null");
|
||||
return new RequestMatcher() {
|
||||
public void match(URI uri, WebServiceMessage request) throws IOException, AssertionError {
|
||||
Node payload = transformToNode(request);
|
||||
String result = expression.evaluateAsString(payload);
|
||||
assertEquals("Evaluation of XPath expression \"" + expressionString + "\" failed.", expectedValue,
|
||||
result);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Node transformToNode(WebServiceMessage request) {
|
||||
DOMResult domResult = new DOMResult();
|
||||
try {
|
||||
transform(request.getPayloadSource(), domResult);
|
||||
return domResult.getNode();
|
||||
}
|
||||
catch (TransformerException ex) {
|
||||
fail("Could not transform request payload: " + ex.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -19,6 +19,7 @@ package org.springframework.ws.mock.client;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.Source;
|
||||
|
||||
@@ -89,7 +90,7 @@ public abstract class WebServiceMock {
|
||||
/**
|
||||
* Expects the payload to validate against the given XSD schema(s).
|
||||
*
|
||||
* @param schema the schema
|
||||
* @param schema the schema
|
||||
* @param furtherSchemas further schemas, if necessary
|
||||
* @return the request matcher
|
||||
*/
|
||||
@@ -107,6 +108,27 @@ public abstract class WebServiceMock {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Expects the given XPath expression to (not) exist or be evaluated to a value.
|
||||
*
|
||||
* @param xpathExpression the XPath expression
|
||||
* @return the XPath expectations, to be further configured
|
||||
*/
|
||||
public static XPathExpectations xpath(String xpathExpression) {
|
||||
return new DefaultXPathExpectations(xpathExpression, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expects the given XPath expression to (not) exist or be evaluated to a value.
|
||||
*
|
||||
* @param xpathExpression the XPath expression
|
||||
* @param namespaceMapping the namespaces
|
||||
* @return the XPath expectations, to be further configured
|
||||
*/
|
||||
public static XPathExpectations xpath(String xpathExpression, Map<String, String> namespaceMapping) {
|
||||
return new DefaultXPathExpectations(xpathExpression, namespaceMapping);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expects the given SOAP header in the outgoing message.
|
||||
*
|
||||
@@ -210,6 +232,7 @@ public abstract class WebServiceMock {
|
||||
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.
|
||||
*
|
||||
@@ -246,7 +269,6 @@ public abstract class WebServiceMock {
|
||||
return SoapFaultResponseCallback.createVersionMismatchFault(faultStringOrReason, locale);
|
||||
}
|
||||
|
||||
|
||||
private static ResourceSource createResourceSource(Resource resource) {
|
||||
try {
|
||||
return new ResourceSource(resource);
|
||||
@@ -256,5 +278,4 @@ public abstract class WebServiceMock {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.client;
|
||||
|
||||
/**
|
||||
* Allows for setting up expectations on XPath expressions. Implementations of this interface are returned by {@link
|
||||
* WebServiceMock}.
|
||||
*
|
||||
* @author Lukas Krecan
|
||||
* @author Arjen Poutsma
|
||||
* @since 2.0
|
||||
*/
|
||||
public interface XPathExpectations {
|
||||
|
||||
/**
|
||||
* Expects the XPath expression to exist.
|
||||
*
|
||||
* @return the request matcher
|
||||
*/
|
||||
RequestMatcher exists();
|
||||
|
||||
/**
|
||||
* Expects the XPath expression to not exist.
|
||||
*
|
||||
* @return the request matcher
|
||||
*/
|
||||
RequestMatcher doesNotExist();
|
||||
|
||||
/**
|
||||
* Expects the XPath expression to evaluate to the given boolean.
|
||||
*
|
||||
* @param expectedValue the expected value
|
||||
* @return the request matcher
|
||||
*/
|
||||
RequestMatcher evaluatesTo(final boolean expectedValue);
|
||||
|
||||
/**
|
||||
* Expects the XPath expression to evaluate to the given integer.
|
||||
*
|
||||
* @param expectedValue the expected value
|
||||
* @return the request matcher
|
||||
*/
|
||||
RequestMatcher evaluatesTo(int expectedValue);
|
||||
|
||||
/**
|
||||
* Expects the XPath expression to evaluate to the given double.
|
||||
*
|
||||
* @param expectedValue the expected value
|
||||
* @return the request matcher
|
||||
*/
|
||||
RequestMatcher evaluatesTo(double expectedValue);
|
||||
|
||||
/**
|
||||
* Expects the XPath expression to evaluate to the given string.
|
||||
*
|
||||
* @param expectedValue the expected value
|
||||
* @return the request matcher
|
||||
*/
|
||||
RequestMatcher evaluatesTo(String expectedValue);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
/*
|
||||
* 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.client;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.ws.WebServiceMessage;
|
||||
import org.springframework.xml.transform.StringSource;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.easymock.EasyMock.*;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
public class DefaultXPathExpectationsTest {
|
||||
|
||||
@Test
|
||||
public void existsMatch() throws IOException, AssertionError {
|
||||
RequestMatcher requestMatcher = WebServiceMock.xpath("//b").exists();
|
||||
assertNotNull(requestMatcher);
|
||||
|
||||
WebServiceMessage message = createMock(WebServiceMessage.class);
|
||||
expect(message.getPayloadSource()).andReturn(new StringSource("<a><b/></a>"));
|
||||
|
||||
replay(message);
|
||||
|
||||
requestMatcher.match(null, message);
|
||||
|
||||
verify(message);
|
||||
}
|
||||
|
||||
@Test(expected = AssertionError.class)
|
||||
public void existsNonMatch() throws IOException, AssertionError {
|
||||
RequestMatcher requestMatcher = WebServiceMock.xpath("//c").exists();
|
||||
assertNotNull(requestMatcher);
|
||||
|
||||
WebServiceMessage message = createMock(WebServiceMessage.class);
|
||||
expect(message.getPayloadSource()).andReturn(new StringSource("<a><b/></a>"));
|
||||
|
||||
replay(message);
|
||||
|
||||
requestMatcher.match(null, message);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void notExistsMatch() throws IOException, AssertionError {
|
||||
RequestMatcher requestMatcher = WebServiceMock.xpath("//c").doesNotExist();
|
||||
assertNotNull(requestMatcher);
|
||||
|
||||
WebServiceMessage message = createMock(WebServiceMessage.class);
|
||||
expect(message.getPayloadSource()).andReturn(new StringSource("<a><b/></a>"));
|
||||
|
||||
replay(message);
|
||||
|
||||
requestMatcher.match(null, message);
|
||||
|
||||
verify(message);
|
||||
}
|
||||
|
||||
@Test(expected = AssertionError.class)
|
||||
public void notExistsNonMatch() throws IOException, AssertionError {
|
||||
RequestMatcher requestMatcher = WebServiceMock.xpath("//a").doesNotExist();
|
||||
assertNotNull(requestMatcher);
|
||||
|
||||
WebServiceMessage message = createMock(WebServiceMessage.class);
|
||||
expect(message.getPayloadSource()).andReturn(new StringSource("<a><b/></a>"));
|
||||
|
||||
replay(message);
|
||||
|
||||
requestMatcher.match(null, message);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void evaluatesToTrueMatch() throws IOException, AssertionError {
|
||||
RequestMatcher requestMatcher = WebServiceMock.xpath("//b=1").evaluatesTo(true);
|
||||
assertNotNull(requestMatcher);
|
||||
|
||||
WebServiceMessage message = createMock(WebServiceMessage.class);
|
||||
expect(message.getPayloadSource()).andReturn(new StringSource("<a><b>1</b></a>"));
|
||||
|
||||
replay(message);
|
||||
|
||||
requestMatcher.match(null, message);
|
||||
|
||||
verify(message);
|
||||
}
|
||||
|
||||
@Test(expected = AssertionError.class)
|
||||
public void evaluatesToTrueNonMatch() throws IOException, AssertionError {
|
||||
RequestMatcher requestMatcher = WebServiceMock.xpath("//b=2").evaluatesTo(true);
|
||||
assertNotNull(requestMatcher);
|
||||
|
||||
WebServiceMessage message = createMock(WebServiceMessage.class);
|
||||
expect(message.getPayloadSource()).andReturn(new StringSource("<a><b>1</b></a>"));
|
||||
|
||||
replay(message);
|
||||
|
||||
requestMatcher.match(null, message);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void evaluatesToFalseMatch() throws IOException, AssertionError {
|
||||
RequestMatcher requestMatcher = WebServiceMock.xpath("//b!=1").evaluatesTo(false);
|
||||
assertNotNull(requestMatcher);
|
||||
|
||||
WebServiceMessage message = createMock(WebServiceMessage.class);
|
||||
expect(message.getPayloadSource()).andReturn(new StringSource("<a><b>1</b></a>"));
|
||||
|
||||
replay(message);
|
||||
|
||||
requestMatcher.match(null, message);
|
||||
|
||||
verify(message);
|
||||
}
|
||||
|
||||
@Test(expected = AssertionError.class)
|
||||
public void evaluatesToFalseNonMatch() throws IOException, AssertionError {
|
||||
RequestMatcher requestMatcher = WebServiceMock.xpath("//b!=2").evaluatesTo(false);
|
||||
assertNotNull(requestMatcher);
|
||||
|
||||
WebServiceMessage message = createMock(WebServiceMessage.class);
|
||||
expect(message.getPayloadSource()).andReturn(new StringSource("<a><b>1</b></a>"));
|
||||
|
||||
replay(message);
|
||||
|
||||
requestMatcher.match(null, message);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void existsWithNamespacesMatch() throws IOException, AssertionError {
|
||||
Map<String, String> ns = Collections.singletonMap("x", "http://example.org");
|
||||
RequestMatcher requestMatcher = WebServiceMock.xpath("//x:b", ns).exists();
|
||||
assertNotNull(requestMatcher);
|
||||
|
||||
WebServiceMessage message = createMock(WebServiceMessage.class);
|
||||
expect(message.getPayloadSource())
|
||||
.andReturn(new StringSource("<a:a xmlns:a=\"http://example.org\"><a:b/></a:a>"));
|
||||
|
||||
replay(message);
|
||||
|
||||
requestMatcher.match(null, message);
|
||||
|
||||
verify(message);
|
||||
}
|
||||
|
||||
@Test(expected = AssertionError.class)
|
||||
public void existsWithNamespacesNonMatch() throws IOException, AssertionError {
|
||||
Map<String, String> ns = Collections.singletonMap("x", "http://example.org");
|
||||
RequestMatcher requestMatcher = WebServiceMock.xpath("//b", ns).exists();
|
||||
assertNotNull(requestMatcher);
|
||||
|
||||
WebServiceMessage message = createMock(WebServiceMessage.class);
|
||||
expect(message.getPayloadSource())
|
||||
.andReturn(new StringSource("<a:a xmlns:a=\"http://example.org\"><a:b/></a:a>"));
|
||||
|
||||
replay(message);
|
||||
|
||||
requestMatcher.match(null, message);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void evaluatesToIntegerMatch() throws IOException, AssertionError {
|
||||
RequestMatcher requestMatcher = WebServiceMock.xpath("//b").evaluatesTo(1);
|
||||
assertNotNull(requestMatcher);
|
||||
|
||||
WebServiceMessage message = createMock(WebServiceMessage.class);
|
||||
expect(message.getPayloadSource()).andReturn(new StringSource("<a><b>1</b></a>"));
|
||||
|
||||
replay(message);
|
||||
|
||||
requestMatcher.match(null, message);
|
||||
|
||||
verify(message);
|
||||
}
|
||||
|
||||
@Test(expected = AssertionError.class)
|
||||
public void evaluatesToIntegerNonMatch() throws IOException, AssertionError {
|
||||
RequestMatcher requestMatcher = WebServiceMock.xpath("//b").evaluatesTo(2);
|
||||
assertNotNull(requestMatcher);
|
||||
|
||||
WebServiceMessage message = createMock(WebServiceMessage.class);
|
||||
expect(message.getPayloadSource()).andReturn(new StringSource("<a><b>1</b></a>"));
|
||||
|
||||
replay(message);
|
||||
|
||||
requestMatcher.match(null, message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,6 +18,8 @@ package org.springframework.ws.mock.client;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.TransformerException;
|
||||
@@ -192,4 +194,25 @@ public class WebServiceMockTest {
|
||||
template.sendSourceAndReceiveToResult(new StringSource(actual), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void xpathExistsMatch() throws Exception {
|
||||
final Map<String, String> ns = Collections.singletonMap("ns", "http://example.com");
|
||||
|
||||
expect(xpath("/ns:request", ns).exists());
|
||||
|
||||
template.sendSourceAndReceiveToResult(new StringSource("<request xmlns='http://example.com'/>"),
|
||||
new StringResult());
|
||||
}
|
||||
|
||||
@Test(expected = AssertionError.class)
|
||||
public void xpathExistsNonMatch() throws Exception {
|
||||
final Map<String, String> ns = Collections.singletonMap("ns", "http://example.com");
|
||||
|
||||
expect(xpath("/ns:foo", ns).exists());
|
||||
|
||||
template.sendSourceAndReceiveToResult(new StringSource("<request xmlns='http://example.com'/>"),
|
||||
new StringResult());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user