From b89cb20b1d63ce482444776e5544e549a4a1deeb Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Fri, 12 Oct 2018 15:41:42 -0400 Subject: [PATCH] Lenient date parsing in HeadersResultMatchers Rather than formatting the expected value, and be susceptible to minor formatting differences (e.g. 01 vs 1 for day of month), parse the actual header value leniently with HttpHeaders and compare time values. Issue: SPR-17330 --- .../servlet/result/HeaderResultMatchers.java | 28 +++++----- .../result/HeaderResultMatchersTests.java | 54 +++++++++++++++++++ .../resultmatchers/HeaderAssertionTests.java | 3 +- 3 files changed, 72 insertions(+), 13 deletions(-) create mode 100644 spring-test/src/test/java/org/springframework/test/web/servlet/result/HeaderResultMatchersTests.java diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/result/HeaderResultMatchers.java b/spring-test/src/main/java/org/springframework/test/web/servlet/result/HeaderResultMatchers.java index d4a10fdf353..b5a686e971b 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/result/HeaderResultMatchers.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/result/HeaderResultMatchers.java @@ -16,20 +16,19 @@ package org.springframework.test.web.servlet.result; -import java.text.SimpleDateFormat; import java.util.Arrays; -import java.util.Date; import java.util.List; -import java.util.Locale; -import java.util.TimeZone; import org.hamcrest.Matcher; +import org.springframework.http.HttpHeaders; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.test.web.servlet.ResultMatcher; -import static org.hamcrest.MatcherAssert.*; -import static org.springframework.test.util.AssertionErrors.*; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.assertNotNull; +import static org.springframework.test.util.AssertionErrors.assertEquals; +import static org.springframework.test.util.AssertionErrors.assertTrue; /** * Factory for response header assertions. @@ -126,7 +125,7 @@ public class HeaderResultMatchers { } /** - * Assert the primary value of the named response header as a date String, + * Assert the primary value of the named response header parsed into a date * using the preferred date format described in RFC 7231. *

The {@link ResultMatcher} returned by this method throws an * {@link AssertionError} if the response does not contain the specified @@ -136,12 +135,17 @@ public class HeaderResultMatchers { */ public ResultMatcher dateValue(final String name, final long value) { return result -> { - SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US); - format.setTimeZone(TimeZone.getTimeZone("GMT")); - String formatted = format.format(new Date(value)); MockHttpServletResponse response = result.getResponse(); - assertTrue("Response does not contain header '" + name + "'", response.containsHeader(name)); - assertEquals("Response header '" + name + "'", formatted, response.getHeader(name)); + String headerValue = response.getHeader(name); + assertNotNull("Response does not contain header '" + name + "'", headerValue); + + HttpHeaders headers = new HttpHeaders(); + headers.setDate("expected", value); + headers.set("actual", headerValue); + + assertEquals("Response header '" + name + "'='" + headerValue + "' " + + "does not match expected value '" + headers.getFirst("expected") + "'", + headers.getFirstDate("expected"), headers.getFirstDate("actual")); }; } diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/result/HeaderResultMatchersTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/result/HeaderResultMatchersTests.java new file mode 100644 index 00000000000..ee9150665d6 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/result/HeaderResultMatchersTests.java @@ -0,0 +1,54 @@ +/* + * Copyright 2002-2018 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.test.web.servlet.result; + +import java.time.ZoneId; +import java.time.ZonedDateTime; + +import org.junit.Test; + +import org.springframework.http.HttpHeaders; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; +import org.springframework.test.web.servlet.MvcResult; +import org.springframework.test.web.servlet.StubMvcResult; + +/** + * Unit tests for {@link HeaderResultMatchers}. + * @author Rossen Stoyanchev + */ +public class HeaderResultMatchersTests { + + private final HeaderResultMatchers matchers = new HeaderResultMatchers(); + + private final MockHttpServletResponse response = new MockHttpServletResponse(); + + private final MvcResult mvcResult = + new StubMvcResult(new MockHttpServletRequest(), null, null, null, null, null, this.response); + + + @Test // SPR-17330 + public void matchDateFormattedWithHttpHeaders() throws Exception { + + long epochMilli = ZonedDateTime.of(2018, 10, 5, 0, 0, 0, 0, ZoneId.of("GMT")).toInstant().toEpochMilli(); + HttpHeaders headers = new HttpHeaders(); + headers.setDate("myDate", epochMilli); + this.response.setHeader("d", headers.getFirst("myDate")); + + this.matchers.dateValue("d", epochMilli).match(this.mvcResult); + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/HeaderAssertionTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/HeaderAssertionTests.java index 7f815d9bcb6..a23dc676b88 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/HeaderAssertionTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/samples/standalone/resultmatchers/HeaderAssertionTests.java @@ -208,7 +208,8 @@ public class HeaderAssertionTests { private void assertMessageContains(AssertionError error, String expected) { String message = error.getMessage(); - assertTrue("Failure message should contain: " + expected, message.contains(expected)); + assertTrue("Failure message should contain [" + expected + "], actual is [" + message + "]", + message.contains(expected)); }