Improve charset management in XpathResultMatchers

Prior to this change, `XpathResultMatchers` and more generally the
`MockHttpServletResponse` would default to ISO-8859-1 encoding even when
it's not supposed to. The Servlet/HTTP specs mention this encoding
for all `text/*` mime types when decoding bodies to Strings, but this
issue is about XML Parsers.

XML Parsers should use the encoding:

* defined in the `Content-Type` response header (if available)
* written in the XML declaration of the document
* "guessed" by a built-in auto-detection mechanism

This commit changes the following:

* XPathMatchers now feed the XML parser with byte arrays instead of
decoded Strings
* the response should be written to `MockHttpServletResponse` using
its OutputStream, and not a PrintWriter which defaults to ISO-8859-1

Issue: SPR-12676
This commit is contained in:
Brian Clozel
2015-06-10 16:14:17 +02:00
parent a421bd2c27
commit f988151163
5 changed files with 101 additions and 60 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 the original author or authors.
* Copyright 2002-2015 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.
@@ -15,11 +15,15 @@
*/
package org.springframework.test.web.servlet.result;
import java.nio.charset.Charset;
import org.hamcrest.Matchers;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.test.web.servlet.StubMvcResult;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;
/**
* Tests for {@link XpathResultMatchers}.
@@ -98,12 +102,25 @@ public class XpathResultMatchersTests {
new XpathResultMatchers("/foo/bar[2]", null).booleanValue(false).match(getStubMvcResult());
}
@Test
public void testStringEncodingDetection() throws Exception {
String content = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" +
"<person><name>Jürgen</name></person>";
byte[] bytes = content.getBytes(Charset.forName("UTF-8"));
MockHttpServletResponse response = new MockHttpServletResponse();
response.addHeader("Content-Type", "application/xml");
StreamUtils.copy(bytes, response.getOutputStream());
StubMvcResult result = new StubMvcResult(null, null, null, null, null, null, response);
new XpathResultMatchers("/person/name", null).string("Jürgen").match(result);
}
private static final String RESPONSE_CONTENT = "<foo><bar>111</bar><bar>true</bar></foo>";
private StubMvcResult getStubMvcResult() throws Exception {
MockHttpServletResponse response = new MockHttpServletResponse();
response.addHeader("Content-Type", "application/json");
response.addHeader("Content-Type", "application/xml");
response.getWriter().print(new String(RESPONSE_CONTENT.getBytes("ISO-8859-1")));
return new StubMvcResult(null, null, null, null, null, null, response);
}