View Javadoc
1   /*
2    * Copyright 2002-2013 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.test.web.servlet.samples.standalone.resultmatchers;
18  
19  import org.junit.Before;
20  import org.junit.Test;
21  
22  import org.springframework.stereotype.Controller;
23  import org.springframework.test.web.Person;
24  import org.springframework.test.web.servlet.MockMvc;
25  import org.springframework.test.web.servlet.ResultMatcher;
26  import org.springframework.web.bind.annotation.PathVariable;
27  import org.springframework.web.bind.annotation.RequestMapping;
28  import org.springframework.web.bind.annotation.ResponseBody;
29  import org.springframework.web.context.request.WebRequest;
30  
31  import static org.hamcrest.CoreMatchers.*;
32  import static org.junit.Assert.*;
33  import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
34  import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
35  import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*;
36  
37  /**
38   * Examples of expectations on response header values.
39   *
40   * @author Rossen Stoyanchev
41   * @author Sam Brannen
42   */
43  public class HeaderAssertionTests {
44  
45  	private static final String EXPECTED_ASSERTION_ERROR_MSG = "Should have thrown an AssertionError";
46  
47  	private static final String IF_MODIFIED_SINCE = "If-Modified-Since";
48  
49  	private static final String LAST_MODIFIED = "Last-Modified";
50  
51  	private final long currentTime = System.currentTimeMillis();
52  
53  	private MockMvc mockMvc;
54  
55  	private PersonController personController;
56  
57  
58  	@Before
59  	public void setup() {
60  		this.personController = new PersonController();
61  		this.personController.setStubTimestamp(currentTime);
62  		this.mockMvc = standaloneSetup(this.personController).build();
63  	}
64  
65  	@Test
66  	public void stringWithCorrectResponseHeaderValue() throws Exception {
67  		this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, currentTime - (1000 * 60)))//
68  		.andExpect(header().string(LAST_MODIFIED, String.valueOf(currentTime)));
69  	}
70  
71  	@Test
72  	public void stringWithMatcherAndCorrectResponseHeaderValue() throws Exception {
73  		this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, currentTime - (1000 * 60)))//
74  		.andExpect(header().string(LAST_MODIFIED, equalTo(String.valueOf(currentTime))));
75  	}
76  
77  	@Test
78  	public void longValueWithCorrectResponseHeaderValue() throws Exception {
79  		this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, currentTime - (1000 * 60)))//
80  		.andExpect(header().longValue(LAST_MODIFIED, currentTime));
81  	}
82  
83  	@Test
84  	public void stringWithMissingResponseHeader() throws Exception {
85  		this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, currentTime))//
86  		.andExpect(status().isNotModified())//
87  		.andExpect(header().string(LAST_MODIFIED, (String) null));
88  	}
89  
90  	@Test
91  	public void stringWithMatcherAndMissingResponseHeader() throws Exception {
92  		this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, currentTime))//
93  		.andExpect(status().isNotModified())//
94  		.andExpect(header().string(LAST_MODIFIED, nullValue()));
95  	}
96  
97  	@Test
98  	public void longValueWithMissingResponseHeader() throws Exception {
99  		try {
100 			this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, currentTime))//
101 			.andExpect(status().isNotModified())//
102 			.andExpect(header().longValue(LAST_MODIFIED, 99L));
103 
104 			fail(EXPECTED_ASSERTION_ERROR_MSG);
105 		}
106 		catch (AssertionError e) {
107 			if (EXPECTED_ASSERTION_ERROR_MSG.equals(e.getMessage())) {
108 				throw e;
109 			}
110 			assertEquals("Response does not contain header " + LAST_MODIFIED, e.getMessage());
111 		}
112 	}
113 
114 	// SPR-10771
115 
116 	@Test
117 	public void doesNotExist() throws Exception {
118 		this.mockMvc.perform(get("/persons/1"))
119 				.andExpect(header().doesNotExist("X-Custom-Header"));
120 	}
121 
122 	// SPR-10771
123 
124 	@Test(expected = AssertionError.class)
125 	public void doesNotExistFail() throws Exception {
126 		this.mockMvc.perform(get("/persons/1"))
127 				.andExpect(header().doesNotExist(LAST_MODIFIED));
128 	}
129 
130 	@Test
131 	public void stringWithIncorrectResponseHeaderValue() throws Exception {
132 		long unexpected = currentTime + 1;
133 		assertIncorrectResponseHeaderValue(header().string(LAST_MODIFIED, String.valueOf(unexpected)), unexpected);
134 	}
135 
136 	@Test
137 	public void stringWithMatcherAndIncorrectResponseHeaderValue() throws Exception {
138 		long unexpected = currentTime + 1;
139 		assertIncorrectResponseHeaderValue(header().string(LAST_MODIFIED, equalTo(String.valueOf(unexpected))),
140 			unexpected);
141 	}
142 
143 	@Test
144 	public void longValueWithIncorrectResponseHeaderValue() throws Exception {
145 		long unexpected = currentTime + 1;
146 		assertIncorrectResponseHeaderValue(header().longValue(LAST_MODIFIED, unexpected), unexpected);
147 	}
148 
149 	private void assertIncorrectResponseHeaderValue(ResultMatcher resultMatcher, long unexpected) throws Exception {
150 		try {
151 			this.mockMvc.perform(get("/persons/1").header(IF_MODIFIED_SINCE, currentTime - (1000 * 60)))//
152 			.andExpect(resultMatcher);
153 
154 			fail(EXPECTED_ASSERTION_ERROR_MSG);
155 		}
156 		catch (AssertionError e) {
157 			if (EXPECTED_ASSERTION_ERROR_MSG.equals(e.getMessage())) {
158 				throw e;
159 			}
160 			// [SPR-10659] Ensure that the header name is included in the message
161 			//
162 			// We don't use assertEquals() since we cannot control the formatting
163 			// produced by JUnit or Hamcrest.
164 			assertMessageContains(e, "Response header " + LAST_MODIFIED);
165 			assertMessageContains(e, String.valueOf(unexpected));
166 			assertMessageContains(e, String.valueOf(currentTime));
167 		}
168 	}
169 
170 	private void assertMessageContains(AssertionError error, String expected) {
171 		String message = error.getMessage();
172 		assertTrue("Failure message should contain: " + expected, message.contains(expected));
173 	}
174 
175 
176 	// -------------------------------------------------------------------------
177 
178 	@Controller
179 	private static class PersonController {
180 
181 		private long timestamp;
182 
183 
184 		public void setStubTimestamp(long timestamp) {
185 			this.timestamp = timestamp;
186 		}
187 
188 		@RequestMapping("/persons/{id}")
189 		@ResponseBody
190 		public Person showEntity(@PathVariable long id, WebRequest request) {
191 			if (request.checkNotModified(calculateLastModified(id))) {
192 				return null;
193 			}
194 			return new Person("Jason");
195 		}
196 
197 		private long calculateLastModified(long id) {
198 			return this.timestamp;
199 		}
200 	}
201 }