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 c57387ee14b..6e53496fa2c 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -18,6 +18,7 @@ package org.springframework.test.web.servlet.result; import org.hamcrest.Matcher; +import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.ResultMatcher; @@ -31,7 +32,7 @@ import java.util.TimeZone; /** * Factory for response header assertions. - *
An instance of this class is usually accessed via + *
An instance of this class is available via * {@link MockMvcResultMatchers#header}. * * @author Rossen Stoyanchev @@ -41,13 +42,15 @@ import java.util.TimeZone; */ public class HeaderResultMatchers { + /** * Protected constructor. - * Use {@link MockMvcResultMatchers#header()}. + * See {@link MockMvcResultMatchers#header()}. */ protected HeaderResultMatchers() { } + /** * Assert the primary value of the named response header with the given * Hamcrest {@link Matcher}. @@ -81,23 +84,25 @@ public class HeaderResultMatchers { return new ResultMatcher() { @Override public void match(MvcResult result) { - assertTrue("Response should not contain header " + name, !result.getResponse().containsHeader(name)); + assertTrue("Response should not contain header " + name, + !result.getResponse().containsHeader(name)); } }; } /** * Assert the primary value of the named response header as a {@code long}. - *
The {@link ResultMatcher} returned by this method throws an {@link AssertionError} - * if the response does not contain the specified header, or if the supplied - * {@code value} does not match the primary value. + *
The {@link ResultMatcher} returned by this method throws an + * {@link AssertionError} if the response does not contain the specified + * header, or if the supplied {@code value} does not match the primary value. */ public ResultMatcher longValue(final String name, final long value) { return new ResultMatcher() { @Override public void match(MvcResult result) { - assertTrue("Response does not contain header " + name, result.getResponse().containsHeader(name)); - assertEquals("Response header " + name, value, Long.parseLong(result.getResponse().getHeader(name))); + MockHttpServletResponse response = result.getResponse(); + assertTrue("Response does not contain header " + name, response.containsHeader(name)); + assertEquals("Response header " + name, value, Long.parseLong(response.getHeader(name))); } }; } @@ -105,10 +110,9 @@ public class HeaderResultMatchers { /** * Assert the primary value of the named response header as a date String, * 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 header, or if the supplied - * {@code value} does not match the primary value. - * + *
The {@link ResultMatcher} returned by this method throws an + * {@link AssertionError} if the response does not contain the specified + * header, or if the supplied {@code value} does not match the primary value. * @see Section 7.1.1.1 of RFC 7231 * @since 4.2 */ @@ -118,8 +122,10 @@ public class HeaderResultMatchers { public void match(MvcResult result) { SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US); format.setTimeZone(TimeZone.getTimeZone("GMT")); - assertTrue("Response does not contain header " + name, result.getResponse().containsHeader(name)); - assertEquals("Response header " + name, format.format(new Date(value)), result.getResponse().getHeader(name)); + 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)); } }; } 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 e81824c8fdc..d9160d8fee6 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -16,6 +16,11 @@ package org.springframework.test.web.servlet.samples.standalone.resultmatchers; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; +import java.util.TimeZone; + import org.junit.Before; import org.junit.Test; @@ -28,16 +33,18 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.context.request.WebRequest; -import static org.hamcrest.CoreMatchers.*; -import static org.junit.Assert.*; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; -import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.springframework.http.HttpHeaders.IF_MODIFIED_SINCE; +import static org.springframework.http.HttpHeaders.LAST_MODIFIED; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; -import java.util.TimeZone; /** * Examples of expectations on response header values. @@ -48,86 +55,83 @@ import java.util.TimeZone; */ public class HeaderAssertionTests { - private static final String EXPECTED_ASSERTION_ERROR_MSG = "Should have thrown an AssertionError"; - - private static final String IF_MODIFIED_SINCE = "If-Modified-Since"; + private static final String ERROR_MESSAGE = "Should have thrown an AssertionError"; - private static final String LAST_MODIFIED = "Last-Modified"; - - private final long currentTime = System.currentTimeMillis(); private String now; - private String oneMinuteAgo; + private String minuteAgo; - private String oneSecondLater; + private String secondLater; private MockMvc mockMvc; - private PersonController personController; + private final long currentTime = System.currentTimeMillis(); @Before public void setup() { SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US); dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); - this.now = dateFormat.format(new Date(currentTime)); - this.oneMinuteAgo = dateFormat.format(new Date(currentTime - (1000 * 60))); - this.oneSecondLater = dateFormat.format(new Date(currentTime + 1000)); - this.personController = new PersonController(); - this.personController.setStubTimestamp(currentTime); - this.mockMvc = standaloneSetup(this.personController).build(); + this.now = dateFormat.format(new Date(this.currentTime)); + this.minuteAgo = dateFormat.format(new Date(this.currentTime - (1000 * 60))); + this.secondLater = dateFormat.format(new Date(this.currentTime + 1000)); + + PersonController controller = new PersonController(); + controller.setStubTimestamp(this.currentTime); + this.mockMvc = standaloneSetup(controller).build(); } + @Test public void stringWithCorrectResponseHeaderValue() throws Exception { - this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, oneMinuteAgo))// - .andExpect(header().string(LAST_MODIFIED, now)); + this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, minuteAgo)) + .andExpect(header().string(LAST_MODIFIED, now)); } @Test public void stringWithMatcherAndCorrectResponseHeaderValue() throws Exception { - this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, oneMinuteAgo))// - .andExpect(header().string(LAST_MODIFIED, equalTo(now))); + this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, minuteAgo)) + .andExpect(header().string(LAST_MODIFIED, equalTo(now))); } @Test public void dateValueWithCorrectResponseHeaderValue() throws Exception { - this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, oneMinuteAgo))// - .andExpect(header().dateValue(LAST_MODIFIED, currentTime)); + this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, minuteAgo)) + .andExpect(header().dateValue(LAST_MODIFIED, this.currentTime)); } @Test public void longValueWithCorrectResponseHeaderValue() throws Exception { - this.mockMvc.perform(get("/persons/1"))// - .andExpect(header().longValue("X-Rate-Limiting", 42)); + this.mockMvc.perform(get("/persons/1")) + .andExpect(header().longValue("X-Rate-Limiting", 42)); } @Test public void stringWithMissingResponseHeader() throws Exception { - this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, now))// - .andExpect(status().isNotModified())// - .andExpect(header().string("X-Custom-Header", (String) null)); + this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, now)) + .andExpect(status().isNotModified()) + .andExpect(header().string("X-Custom-Header", (String) null)); } @Test public void stringWithMatcherAndMissingResponseHeader() throws Exception { - this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, now))// - .andExpect(status().isNotModified())// - .andExpect(header().string("X-Custom-Header", nullValue())); + this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, now)) + .andExpect(status().isNotModified()) + .andExpect(header().string("X-Custom-Header", nullValue())); } @Test public void longValueWithMissingResponseHeader() throws Exception { try { - this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, now))// - .andExpect(status().isNotModified())// - .andExpect(header().longValue("X-Custom-Header", 99L)); + this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, now)) + .andExpect(status().isNotModified()) + .andExpect(header().longValue("X-Custom-Header", 99L)); - fail(EXPECTED_ASSERTION_ERROR_MSG); + fail(ERROR_MESSAGE); } catch (AssertionError e) { - if (EXPECTED_ASSERTION_ERROR_MSG.equals(e.getMessage())) { + if (ERROR_MESSAGE.equals(e.getMessage())) { throw e; } assertEquals("Response does not contain header " + "X-Custom-Header", e.getMessage()); @@ -138,32 +142,30 @@ public class HeaderAssertionTests { @Test public void doesNotExist() throws Exception { - this.mockMvc.perform(get("/persons/1")) - .andExpect(header().doesNotExist("X-Custom-Header")); + this.mockMvc.perform(get("/persons/1")).andExpect(header().doesNotExist("X-Custom-Header")); } // SPR-10771 @Test(expected = AssertionError.class) public void doesNotExistFail() throws Exception { - this.mockMvc.perform(get("/persons/1")) - .andExpect(header().doesNotExist(LAST_MODIFIED)); + this.mockMvc.perform(get("/persons/1")).andExpect(header().doesNotExist(LAST_MODIFIED)); } @Test public void stringWithIncorrectResponseHeaderValue() throws Exception { - assertIncorrectResponseHeaderValue(header().string(LAST_MODIFIED, oneSecondLater), oneSecondLater); + assertIncorrectResponseHeader(header().string(LAST_MODIFIED, secondLater), secondLater); } @Test public void stringWithMatcherAndIncorrectResponseHeaderValue() throws Exception { - assertIncorrectResponseHeaderValue(header().string(LAST_MODIFIED, equalTo(oneSecondLater)), oneSecondLater); + assertIncorrectResponseHeader(header().string(LAST_MODIFIED, equalTo(secondLater)), secondLater); } @Test public void dateValueWithIncorrectResponseHeaderValue() throws Exception { - long unexpected = currentTime + 1000; - assertIncorrectResponseHeaderValue(header().dateValue(LAST_MODIFIED, unexpected), oneSecondLater); + long unexpected = this.currentTime + 1000; + assertIncorrectResponseHeader(header().dateValue(LAST_MODIFIED, unexpected), secondLater); } @Test(expected = AssertionError.class) @@ -171,21 +173,20 @@ public class HeaderAssertionTests { this.mockMvc.perform(get("/persons/1")).andExpect(header().longValue("X-Rate-Limiting", 1)); } - private void assertIncorrectResponseHeaderValue(ResultMatcher resultMatcher, String unexpected) throws Exception { + private void assertIncorrectResponseHeader(ResultMatcher matcher, String unexpected) throws Exception { try { - this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, oneMinuteAgo))// - .andExpect(resultMatcher); + this.mockMvc.perform(get("/persons/1") + .header(IF_MODIFIED_SINCE, minuteAgo)) + .andExpect(matcher); - fail(EXPECTED_ASSERTION_ERROR_MSG); + fail(ERROR_MESSAGE); } catch (AssertionError e) { - if (EXPECTED_ASSERTION_ERROR_MSG.equals(e.getMessage())) { + if (ERROR_MESSAGE.equals(e.getMessage())) { throw e; } - // [SPR-10659] Ensure that the header name is included in the message - // - // We don't use assertEquals() since we cannot control the formatting - // produced by JUnit or Hamcrest. + // SPR-10659: ensure header name is in the message + // Unfortunately, we can't control formatting from JUnit or Hamcrest. assertMessageContains(e, "Response header " + LAST_MODIFIED); assertMessageContains(e, unexpected); assertMessageContains(e, now); @@ -198,9 +199,8 @@ public class HeaderAssertionTests { } - // ------------------------------------------------------------------------- - @Controller + @SuppressWarnings("unused") private static class PersonController { private long timestamp; @@ -216,6 +216,7 @@ public class HeaderAssertionTests { .ok() .lastModified(calculateLastModified(id)) .header("X-Rate-Limiting", "42") + .header("Vary", "foo", "bar") .body(new Person("Jason")); }