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
This commit is contained in:
parent
c5ca56bd50
commit
658c7f99d7
|
@ -16,19 +16,17 @@
|
||||||
|
|
||||||
package org.springframework.test.web.servlet.result;
|
package org.springframework.test.web.servlet.result;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.TimeZone;
|
|
||||||
|
|
||||||
import org.hamcrest.Matcher;
|
import org.hamcrest.Matcher;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.mock.web.MockHttpServletResponse;
|
import org.springframework.mock.web.MockHttpServletResponse;
|
||||||
import org.springframework.test.web.servlet.ResultMatcher;
|
import org.springframework.test.web.servlet.ResultMatcher;
|
||||||
|
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
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.assertEquals;
|
||||||
import static org.springframework.test.util.AssertionErrors.assertTrue;
|
import static org.springframework.test.util.AssertionErrors.assertTrue;
|
||||||
|
|
||||||
|
@ -127,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.
|
* using the preferred date format described in RFC 7231.
|
||||||
* <p>The {@link ResultMatcher} returned by this method throws an
|
* <p>The {@link ResultMatcher} returned by this method throws an
|
||||||
* {@link AssertionError} if the response does not contain the specified
|
* {@link AssertionError} if the response does not contain the specified
|
||||||
|
@ -137,12 +135,17 @@ public class HeaderResultMatchers {
|
||||||
*/
|
*/
|
||||||
public ResultMatcher dateValue(final String name, final long value) {
|
public ResultMatcher dateValue(final String name, final long value) {
|
||||||
return result -> {
|
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();
|
MockHttpServletResponse response = result.getResponse();
|
||||||
assertTrue("Response does not contain header '" + name + "'", response.containsHeader(name));
|
String headerValue = response.getHeader(name);
|
||||||
assertEquals("Response header '" + name + "'", formatted, 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"));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -208,7 +208,8 @@ public class HeaderAssertionTests {
|
||||||
|
|
||||||
private void assertMessageContains(AssertionError error, String expected) {
|
private void assertMessageContains(AssertionError error, String expected) {
|
||||||
String message = error.getMessage();
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue