|
|
|
|
@ -1,5 +1,5 @@
@@ -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 @@
@@ -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;
@@ -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;
@@ -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 {
@@ -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 {
@@ -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 {
@@ -198,9 +199,8 @@ public class HeaderAssertionTests {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
@Controller |
|
|
|
|
@SuppressWarnings("unused") |
|
|
|
|
private static class PersonController { |
|
|
|
|
|
|
|
|
|
private long timestamp; |
|
|
|
|
@ -216,6 +216,7 @@ public class HeaderAssertionTests {
@@ -216,6 +216,7 @@ public class HeaderAssertionTests {
|
|
|
|
|
.ok() |
|
|
|
|
.lastModified(calculateLastModified(id)) |
|
|
|
|
.header("X-Rate-Limiting", "42") |
|
|
|
|
.header("Vary", "foo", "bar") |
|
|
|
|
.body(new Person("Jason")); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|