From 5d92a85fcbce98d680d91287eb24697456786a8b Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Tue, 11 Apr 2017 07:01:20 -0400 Subject: [PATCH] Mock Servlet request/response support Accept-Language Issue: SPR-15209 --- .../mock/web/MockHttpServletRequest.java | 19 +++++++++++++- .../mock/web/MockHttpServletResponse.java | 10 +++++++ .../htmlunit/HtmlUnitRequestBuilder.java | 22 ---------------- .../mock/web/MockHttpServletRequestTests.java | 11 ++++++++ .../htmlunit/HtmlUnitRequestBuilderTests.java | 26 +++++++++++-------- .../mock/web/test/MockHttpServletRequest.java | 19 +++++++++++++- .../web/test/MockHttpServletResponse.java | 10 +++++++ .../i18n/AcceptHeaderLocaleResolverTests.java | 4 +-- 8 files changed, 84 insertions(+), 37 deletions(-) diff --git a/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java b/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java index 099c62d91f..c6356c552f 100644 --- a/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java +++ b/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java @@ -740,6 +740,7 @@ public class MockHttpServletRequest implements HttpServletRequest { public void addPreferredLocale(Locale locale) { Assert.notNull(locale, "Locale must not be null"); this.locales.add(0, locale); + updateAcceptLanguageHeader(); } /** @@ -752,6 +753,13 @@ public class MockHttpServletRequest implements HttpServletRequest { Assert.notEmpty(locales, "Locale list must not be empty"); this.locales.clear(); this.locales.addAll(locales); + updateAcceptLanguageHeader(); + } + + private void updateAcceptLanguageHeader() { + HttpHeaders headers = new HttpHeaders(); + headers.setAcceptLanguageAsLocales(this.locales); + doAddHeaderValue(HttpHeaders.ACCEPT_LANGUAGE, headers.getFirst(HttpHeaders.ACCEPT_LANGUAGE), true); } /** @@ -951,9 +959,18 @@ public class MockHttpServletRequest implements HttpServletRequest { * @see #getDateHeader */ public void addHeader(String name, Object value) { - if (HttpHeaders.CONTENT_TYPE.equalsIgnoreCase(name) && !this.headers.containsKey(HttpHeaders.CONTENT_TYPE)) { + if (HttpHeaders.CONTENT_TYPE.equalsIgnoreCase(name) && + !this.headers.containsKey(HttpHeaders.CONTENT_TYPE)) { + setContentType(value.toString()); } + else if (HttpHeaders.ACCEPT_LANGUAGE.equalsIgnoreCase(name) && + !this.headers.containsKey(HttpHeaders.ACCEPT_LANGUAGE)) { + + HttpHeaders headers = new HttpHeaders(); + headers.add(HttpHeaders.ACCEPT_LANGUAGE, value.toString()); + setPreferredLocales(headers.getAcceptLanguageAsLocales()); + } else { this.cookieHeaderSet = HttpHeaders.COOKIE.equalsIgnoreCase(name); doAddHeaderValue(name, value, false); diff --git a/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java b/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java index 1060991609..2f49908287 100644 --- a/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java +++ b/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletResponse.java @@ -304,6 +304,9 @@ public class MockHttpServletResponse implements HttpServletResponse { @Override public void setLocale(Locale locale) { this.locale = locale; + if (locale != null) { + doAddHeaderValue(HttpHeaders.ACCEPT_LANGUAGE, locale.toLanguageTag(), true); + } } @Override @@ -577,6 +580,13 @@ public class MockHttpServletResponse implements HttpServletResponse { Integer.parseInt(value.toString())); return true; } + else if (HttpHeaders.ACCEPT_LANGUAGE.equalsIgnoreCase(name)) { + HttpHeaders headers = new HttpHeaders(); + headers.add(HttpHeaders.ACCEPT_LANGUAGE, value.toString()); + List locales = headers.getAcceptLanguageAsLocales(); + setLocale(locales.isEmpty() ? null : locales.get(0)); + return true; + } else { return false; } diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/HtmlUnitRequestBuilder.java b/spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/HtmlUnitRequestBuilder.java index 29e54519b4..cc19e360a2 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/HtmlUnitRequestBuilder.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/HtmlUnitRequestBuilder.java @@ -29,7 +29,6 @@ import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.StringTokenizer; -import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.servlet.ServletContext; import javax.servlet.http.Cookie; @@ -353,12 +352,6 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable { if (locale == null) { request.addPreferredLocale(Locale.getDefault()); } - else { - String[] tokens = StringUtils.tokenizeToStringArray(locale, ","); - for (int i = tokens.length - 1; i >= 0; i--) { - request.addPreferredLocale(parseLocale(tokens[i])); - } - } } private void params(MockHttpServletRequest request, UriComponents uriComponents) { @@ -384,21 +377,6 @@ final class HtmlUnitRequestBuilder implements RequestBuilder, Mergeable { } } - private Locale parseLocale(String locale) { - Matcher matcher = LOCALE_PATTERN.matcher(locale); - Assert.isTrue(matcher.matches(), () -> "Invalid locale value [" + locale + "]"); - String language = matcher.group(1); - String country = matcher.group(2); - if (country == null) { - country = ""; - } - String qualifier = matcher.group(3); - if (qualifier == null) { - qualifier = ""; - } - return new Locale(language, country, qualifier); - } - private void servletPath(MockHttpServletRequest request, String requestPath) { String servletPath = requestPath.substring(request.getContextPath().length()); if ("".equals(servletPath)) { diff --git a/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletRequestTests.java b/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletRequestTests.java index af1bef380a..e93e728b3d 100644 --- a/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletRequestTests.java +++ b/spring-test/src/test/java/org/springframework/mock/web/MockHttpServletRequestTests.java @@ -33,6 +33,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.springframework.http.HttpHeaders; import org.springframework.util.StreamUtils; import static org.junit.Assert.*; @@ -297,6 +298,16 @@ public class MockHttpServletRequestTests { List preferredLocales = Arrays.asList(Locale.ITALY, Locale.CHINA); request.setPreferredLocales(preferredLocales); assertEqualEnumerations(Collections.enumeration(preferredLocales), request.getLocales()); + assertEquals("it-it, zh-cn", request.getHeader(HttpHeaders.ACCEPT_LANGUAGE)); + } + + @Test + public void preferredLocalesFromAcceptLanguageHeader() { + String headerValue = "fr-ch, fr;q=0.9, en-*;q=0.8, de;q=0.7, *;q=0.5"; + request.addHeader("Accept-Language", headerValue); + List actual = Collections.list(request.getLocales()); + assertEquals(Arrays.asList(Locale.forLanguageTag("fr-ch"), Locale.forLanguageTag("fr"), + Locale.forLanguageTag("en"), Locale.forLanguageTag("de")), actual); } @Test diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/HtmlUnitRequestBuilderTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/HtmlUnitRequestBuilderTests.java index 94702c4329..3a3e6debf6 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/HtmlUnitRequestBuilderTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/HtmlUnitRequestBuilderTests.java @@ -45,10 +45,16 @@ import org.springframework.test.util.ReflectionTestUtils; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import static java.util.Arrays.*; -import static org.hamcrest.Matchers.*; -import static org.junit.Assert.*; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static java.util.Arrays.asList; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.isEmptyString; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.nullValue; +import static org.hamcrest.Matchers.sameInstance; +import static org.junit.Assert.assertThat; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; /** * Unit tests for {@link HtmlUnitRequestBuilder}. @@ -291,16 +297,16 @@ public class HtmlUnitRequestBuilderTests { MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); - assertThat(actualRequest.getLocale(), equalTo(new Locale("en", "gb", "0.8"))); + assertThat(actualRequest.getLocale(), equalTo(new Locale("en", "gb"))); } @Test public void buildRequestLocaleEnQ07() { - webRequest.setAdditionalHeader("Accept-Language", "en;q=0.7"); + webRequest.setAdditionalHeader("Accept-Language", "en"); MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); - assertThat(actualRequest.getLocale(), equalTo(new Locale("en", "", "0.7"))); + assertThat(actualRequest.getLocale(), equalTo(new Locale("en", ""))); } @Test @@ -323,13 +329,11 @@ public class HtmlUnitRequestBuilderTests { @Test public void buildRequestLocaleMulti() { - webRequest.setAdditionalHeader("Accept-Language", "da, en-gb;q=0.8, en;q=0.7"); + webRequest.setAdditionalHeader("Accept-Language", "en-gb;q=0.8, da, en;q=0.7"); MockHttpServletRequest actualRequest = requestBuilder.buildRequest(servletContext); - // Append Locale.ENGLISH since MockHttpServletRequest automatically sets it as the - // preferred locale. - List expected = asList(new Locale("da"), new Locale("en", "gb", "0.8"), new Locale("en", "", "0.7"), Locale.ENGLISH); + List expected = asList(new Locale("da"), new Locale("en", "gb"), new Locale("en", "")); assertThat(Collections.list(actualRequest.getLocales()), equalTo(expected)); } diff --git a/spring-web/src/test/java/org/springframework/mock/web/test/MockHttpServletRequest.java b/spring-web/src/test/java/org/springframework/mock/web/test/MockHttpServletRequest.java index 100a18c83b..ad320cad55 100644 --- a/spring-web/src/test/java/org/springframework/mock/web/test/MockHttpServletRequest.java +++ b/spring-web/src/test/java/org/springframework/mock/web/test/MockHttpServletRequest.java @@ -740,6 +740,7 @@ public class MockHttpServletRequest implements HttpServletRequest { public void addPreferredLocale(Locale locale) { Assert.notNull(locale, "Locale must not be null"); this.locales.add(0, locale); + updateAcceptLanguageHeader(); } /** @@ -752,6 +753,13 @@ public class MockHttpServletRequest implements HttpServletRequest { Assert.notEmpty(locales, "Locale list must not be empty"); this.locales.clear(); this.locales.addAll(locales); + updateAcceptLanguageHeader(); + } + + private void updateAcceptLanguageHeader() { + HttpHeaders headers = new HttpHeaders(); + headers.setAcceptLanguageAsLocales(this.locales); + doAddHeaderValue(HttpHeaders.ACCEPT_LANGUAGE, headers.getFirst(HttpHeaders.ACCEPT_LANGUAGE), true); } /** @@ -951,9 +959,18 @@ public class MockHttpServletRequest implements HttpServletRequest { * @see #getDateHeader */ public void addHeader(String name, Object value) { - if (HttpHeaders.CONTENT_TYPE.equalsIgnoreCase(name) && !this.headers.containsKey(HttpHeaders.CONTENT_TYPE)) { + if (HttpHeaders.CONTENT_TYPE.equalsIgnoreCase(name) && + !this.headers.containsKey(HttpHeaders.CONTENT_TYPE)) { + setContentType(value.toString()); } + else if (HttpHeaders.ACCEPT_LANGUAGE.equalsIgnoreCase(name) && + !this.headers.containsKey(HttpHeaders.ACCEPT_LANGUAGE)) { + + HttpHeaders headers = new HttpHeaders(); + headers.add(HttpHeaders.ACCEPT_LANGUAGE, value.toString()); + setPreferredLocales(headers.getAcceptLanguageAsLocales()); + } else { this.cookieHeaderSet = HttpHeaders.COOKIE.equalsIgnoreCase(name); doAddHeaderValue(name, value, false); diff --git a/spring-web/src/test/java/org/springframework/mock/web/test/MockHttpServletResponse.java b/spring-web/src/test/java/org/springframework/mock/web/test/MockHttpServletResponse.java index 17c5fe2974..ce6b73b218 100644 --- a/spring-web/src/test/java/org/springframework/mock/web/test/MockHttpServletResponse.java +++ b/spring-web/src/test/java/org/springframework/mock/web/test/MockHttpServletResponse.java @@ -304,6 +304,9 @@ public class MockHttpServletResponse implements HttpServletResponse { @Override public void setLocale(Locale locale) { this.locale = locale; + if (locale != null) { + doAddHeaderValue(HttpHeaders.ACCEPT_LANGUAGE, locale.toLanguageTag(), true); + } } @Override @@ -577,6 +580,13 @@ public class MockHttpServletResponse implements HttpServletResponse { Integer.parseInt(value.toString())); return true; } + else if (HttpHeaders.ACCEPT_LANGUAGE.equalsIgnoreCase(name)) { + HttpHeaders headers = new HttpHeaders(); + headers.add(HttpHeaders.ACCEPT_LANGUAGE, value.toString()); + List locales = headers.getAcceptLanguageAsLocales(); + setLocale(locales.isEmpty() ? null : locales.get(0)); + return true; + } else { return false; } diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/i18n/AcceptHeaderLocaleResolverTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/i18n/AcceptHeaderLocaleResolverTests.java index b22100b559..70695effb5 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/i18n/AcceptHeaderLocaleResolverTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/i18n/AcceptHeaderLocaleResolverTests.java @@ -63,7 +63,7 @@ public class AcceptHeaderLocaleResolverTests { this.resolver.setDefaultLocale(Locale.JAPAN); MockHttpServletRequest request = new MockHttpServletRequest(); - request.addHeader("Accept-Language", KOREA.toString()); + request.addHeader("Accept-Language", KOREA.toLanguageTag()); request.setPreferredLocales(Collections.singletonList(KOREA)); assertEquals(Locale.JAPAN, this.resolver.resolveLocale(request)); } @@ -74,7 +74,7 @@ public class AcceptHeaderLocaleResolverTests { MockHttpServletRequest request = new MockHttpServletRequest(); assertEquals(JAPANESE, this.resolver.resolveLocale(request)); - request.addHeader("Accept-Language", US.toString()); + request.addHeader("Accept-Language", US.toLanguageTag()); request.setPreferredLocales(Collections.singletonList(US)); assertEquals(US, this.resolver.resolveLocale(request)); }