001/* 002 * Copyright 2002-2017 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.test.web.servlet.result; 018 019import java.util.Map; 020import javax.xml.xpath.XPathExpressionException; 021 022import org.hamcrest.Matcher; 023import org.w3c.dom.Node; 024 025import org.springframework.mock.web.MockHttpServletResponse; 026import org.springframework.test.util.XpathExpectationsHelper; 027import org.springframework.test.web.servlet.MvcResult; 028import org.springframework.test.web.servlet.ResultMatcher; 029 030/** 031 * Factory for assertions on the response content using XPath expressions. 032 * 033 * <p>An instance of this class is typically accessed via 034 * {@link MockMvcResultMatchers#xpath}. 035 * 036 * @author Rossen Stoyanchev 037 * @since 3.2 038 */ 039public class XpathResultMatchers { 040 041 private final XpathExpectationsHelper xpathHelper; 042 043 044 /** 045 * Protected constructor, not for direct instantiation. Use 046 * {@link MockMvcResultMatchers#xpath(String, Object...)} or 047 * {@link MockMvcResultMatchers#xpath(String, Map, Object...)}. 048 * @param expression the XPath expression 049 * @param namespaces XML namespaces referenced in the XPath expression, or {@code null} 050 * @param args arguments to parameterize the XPath expression with using the 051 * formatting specifiers defined in {@link String#format(String, Object...)} 052 */ 053 protected XpathResultMatchers(String expression, Map<String, String> namespaces, Object ... args) 054 throws XPathExpressionException { 055 056 this.xpathHelper = new XpathExpectationsHelper(expression, namespaces, args); 057 } 058 059 060 /** 061 * Evaluate the XPath and assert the {@link Node} content found with the 062 * given Hamcrest {@link Matcher}. 063 */ 064 public ResultMatcher node(final Matcher<? super Node> matcher) { 065 return new ResultMatcher() { 066 @Override 067 public void match(MvcResult result) throws Exception { 068 MockHttpServletResponse response = result.getResponse(); 069 xpathHelper.assertNode(response.getContentAsByteArray(), getDefinedEncoding(response), matcher); 070 } 071 }; 072 } 073 074 /** 075 * Get the response encoding if explicitly defined in the response, {code null} otherwise. 076 */ 077 private String getDefinedEncoding(MockHttpServletResponse response) { 078 return response.isCharset() ? response.getCharacterEncoding() : null; 079 } 080 081 /** 082 * Evaluate the XPath and assert that content exists. 083 */ 084 public ResultMatcher exists() { 085 return new ResultMatcher() { 086 @Override 087 public void match(MvcResult result) throws Exception { 088 MockHttpServletResponse response = result.getResponse(); 089 xpathHelper.exists(response.getContentAsByteArray(), getDefinedEncoding(response)); 090 } 091 }; 092 } 093 094 /** 095 * Evaluate the XPath and assert that content doesn't exist. 096 */ 097 public ResultMatcher doesNotExist() { 098 return new ResultMatcher() { 099 @Override 100 public void match(MvcResult result) throws Exception { 101 MockHttpServletResponse response = result.getResponse(); 102 xpathHelper.doesNotExist(response.getContentAsByteArray(), getDefinedEncoding(response)); 103 } 104 }; 105 } 106 107 /** 108 * Evaluate the XPath and assert the number of nodes found with the given 109 * Hamcrest {@link Matcher}. 110 */ 111 public ResultMatcher nodeCount(final Matcher<Integer> matcher) { 112 return new ResultMatcher() { 113 @Override 114 public void match(MvcResult result) throws Exception { 115 MockHttpServletResponse response = result.getResponse(); 116 xpathHelper.assertNodeCount(response.getContentAsByteArray(), getDefinedEncoding(response), matcher); 117 } 118 }; 119 } 120 121 /** 122 * Evaluate the XPath and assert the number of nodes found. 123 */ 124 public ResultMatcher nodeCount(final int expectedCount) { 125 return new ResultMatcher() { 126 @Override 127 public void match(MvcResult result) throws Exception { 128 MockHttpServletResponse response = result.getResponse(); 129 xpathHelper.assertNodeCount(response.getContentAsByteArray(), getDefinedEncoding(response), expectedCount); 130 } 131 }; 132 } 133 134 /** 135 * Apply the XPath and assert the {@link String} value found with the given 136 * Hamcrest {@link Matcher}. 137 */ 138 public ResultMatcher string(final Matcher<? super String> matcher) { 139 return new ResultMatcher() { 140 @Override 141 public void match(MvcResult result) throws Exception { 142 MockHttpServletResponse response = result.getResponse(); 143 xpathHelper.assertString(response.getContentAsByteArray(), getDefinedEncoding(response), matcher); 144 } 145 }; 146 } 147 148 /** 149 * Apply the XPath and assert the {@link String} value found. 150 */ 151 public ResultMatcher string(final String expectedValue) { 152 return new ResultMatcher() { 153 @Override 154 public void match(MvcResult result) throws Exception { 155 MockHttpServletResponse response = result.getResponse(); 156 xpathHelper.assertString(response.getContentAsByteArray(), getDefinedEncoding(response), expectedValue); 157 } 158 }; 159 } 160 161 /** 162 * Evaluate the XPath and assert the {@link Double} value found with the 163 * given Hamcrest {@link Matcher}. 164 */ 165 public ResultMatcher number(final Matcher<? super Double> matcher) { 166 return new ResultMatcher() { 167 @Override 168 public void match(MvcResult result) throws Exception { 169 MockHttpServletResponse response = result.getResponse(); 170 xpathHelper.assertNumber(response.getContentAsByteArray(), getDefinedEncoding(response), matcher); 171 } 172 }; 173 } 174 175 /** 176 * Evaluate the XPath and assert the {@link Double} value found. 177 */ 178 public ResultMatcher number(final Double expectedValue) { 179 return new ResultMatcher() { 180 @Override 181 public void match(MvcResult result) throws Exception { 182 MockHttpServletResponse response = result.getResponse(); 183 xpathHelper.assertNumber(response.getContentAsByteArray(), getDefinedEncoding(response), expectedValue); 184 } 185 }; 186 } 187 188 /** 189 * Evaluate the XPath and assert the {@link Boolean} value found. 190 */ 191 public ResultMatcher booleanValue(final Boolean value) { 192 return new ResultMatcher() { 193 @Override 194 public void match(MvcResult result) throws Exception { 195 MockHttpServletResponse response = result.getResponse(); 196 xpathHelper.assertBoolean(response.getContentAsByteArray(), getDefinedEncoding(response), value); 197 } 198 }; 199 } 200 201}