001/*
002 * Copyright 2002-2017 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.test.web.servlet.result;
018
019import org.hamcrest.Matcher;
020
021import org.springframework.http.HttpStatus;
022import org.springframework.test.web.servlet.MvcResult;
023import org.springframework.test.web.servlet.ResultMatcher;
024
025import static org.hamcrest.MatcherAssert.*;
026import static org.springframework.test.util.AssertionErrors.*;
027
028/**
029 * Factory for assertions on the response status.
030 *
031 * <p>An instance of this class is typically accessed via
032 * {@link MockMvcResultMatchers#status}.
033 *
034 * @author Keesun Baik
035 * @author Rossen Stoyanchev
036 * @author Sebastien Deleuze
037 * @author Brian Clozel
038 * @since 3.2
039 */
040public class StatusResultMatchers {
041
042        /**
043         * Protected constructor.
044         * Use {@link MockMvcResultMatchers#status()}.
045         */
046        protected StatusResultMatchers() {
047        }
048
049
050        /**
051         * Assert the response status code with the given Hamcrest {@link Matcher}.
052         */
053        public ResultMatcher is(final Matcher<Integer> matcher) {
054                return new ResultMatcher() {
055                        @Override
056                        public void match(MvcResult result) throws Exception {
057                                assertThat("Response status", result.getResponse().getStatus(), matcher);
058                        }
059                };
060        }
061
062        /**
063         * Assert the response status code is equal to an integer value.
064         */
065        public ResultMatcher is(final int status) {
066                return new ResultMatcher() {
067                        @Override
068                        public void match(MvcResult result) throws Exception {
069                                assertEquals("Response status", status, result.getResponse().getStatus());
070                        }
071                };
072        }
073
074        /**
075         * Assert the response status code is in the 1xx range.
076         */
077        public ResultMatcher is1xxInformational() {
078                return new ResultMatcher() {
079                        @Override
080                        public void match(MvcResult result) throws Exception {
081                                assertEquals("Range for response status value " + result.getResponse().getStatus(),
082                                                HttpStatus.Series.INFORMATIONAL, getHttpStatusSeries(result));
083                        }
084                };
085        }
086
087        /**
088         * Assert the response status code is in the 2xx range.
089         */
090        public ResultMatcher is2xxSuccessful() {
091                return new ResultMatcher() {
092                        @Override
093                        public void match(MvcResult result) throws Exception {
094                                assertEquals("Range for response status value " + result.getResponse().getStatus(),
095                                                HttpStatus.Series.SUCCESSFUL, getHttpStatusSeries(result));
096                        }
097                };
098        }
099
100        /**
101         * Assert the response status code is in the 3xx range.
102         */
103        public ResultMatcher is3xxRedirection() {
104                return new ResultMatcher() {
105                        @Override
106                        public void match(MvcResult result) throws Exception {
107                                assertEquals("Range for response status value " + result.getResponse().getStatus(),
108                                                HttpStatus.Series.REDIRECTION, getHttpStatusSeries(result));
109                        }
110                };
111        }
112
113        /**
114         * Assert the response status code is in the 4xx range.
115         */
116        public ResultMatcher is4xxClientError() {
117                return new ResultMatcher() {
118                        @Override
119                        public void match(MvcResult result) throws Exception {
120                                assertEquals("Range for response status value " + result.getResponse().getStatus(),
121                                                HttpStatus.Series.CLIENT_ERROR, getHttpStatusSeries(result));
122                        }
123                };
124        }
125
126        /**
127         * Assert the response status code is in the 5xx range.
128         */
129        public ResultMatcher is5xxServerError() {
130                return new ResultMatcher() {
131                        @Override
132                        public void match(MvcResult result) throws Exception {
133                                assertEquals("Range for response status value " + result.getResponse().getStatus(),
134                                                HttpStatus.Series.SERVER_ERROR, getHttpStatusSeries(result));
135                        }
136                };
137        }
138
139        private HttpStatus.Series getHttpStatusSeries(MvcResult result) {
140                int statusValue = result.getResponse().getStatus();
141                HttpStatus status = HttpStatus.valueOf(statusValue);
142                return status.series();
143        }
144
145        /**
146         * Assert the Servlet response error message with the given Hamcrest {@link Matcher}.
147         */
148        public ResultMatcher reason(final Matcher<? super String> matcher) {
149                return new ResultMatcher() {
150                        @Override
151                        public void match(MvcResult result) throws Exception {
152                                assertThat("Response status reason", result.getResponse().getErrorMessage(), matcher);
153                        }
154                };
155        }
156
157        /**
158         * Assert the Servlet response error message.
159         */
160        public ResultMatcher reason(final String reason) {
161                return new ResultMatcher() {
162                        @Override
163                        public void match(MvcResult result) throws Exception {
164                                assertEquals("Response status reason", reason, result.getResponse().getErrorMessage());
165                        }
166                };
167        }
168
169        /**
170         * Assert the response status code is {@code HttpStatus.CONTINUE} (100).
171         */
172        public ResultMatcher isContinue() {
173                return matcher(HttpStatus.CONTINUE);
174        }
175
176        /**
177         * Assert the response status code is {@code HttpStatus.SWITCHING_PROTOCOLS} (101).
178         */
179        public ResultMatcher isSwitchingProtocols() {
180                return matcher(HttpStatus.SWITCHING_PROTOCOLS);
181        }
182
183        /**
184         * Assert the response status code is {@code HttpStatus.PROCESSING} (102).
185         */
186        public ResultMatcher isProcessing() {
187                return matcher(HttpStatus.PROCESSING);
188        }
189
190        /**
191         * Assert the response status code is {@code HttpStatus.CHECKPOINT} (103).
192         */
193        public ResultMatcher isCheckpoint() {
194                return matcher(HttpStatus.valueOf(103));
195        }
196
197        /**
198         * Assert the response status code is {@code HttpStatus.OK} (200).
199         */
200        public ResultMatcher isOk() {
201                return matcher(HttpStatus.OK);
202        }
203
204        /**
205         * Assert the response status code is {@code HttpStatus.CREATED} (201).
206         */
207        public ResultMatcher isCreated() {
208                return matcher(HttpStatus.CREATED);
209        }
210
211        /**
212         * Assert the response status code is {@code HttpStatus.ACCEPTED} (202).
213         */
214        public ResultMatcher isAccepted() {
215                return matcher(HttpStatus.ACCEPTED);
216        }
217
218        /**
219         * Assert the response status code is {@code HttpStatus.NON_AUTHORITATIVE_INFORMATION} (203).
220         */
221        public ResultMatcher isNonAuthoritativeInformation() {
222                return matcher(HttpStatus.NON_AUTHORITATIVE_INFORMATION);
223        }
224
225        /**
226         * Assert the response status code is {@code HttpStatus.NO_CONTENT} (204).
227         */
228        public ResultMatcher isNoContent() {
229                return matcher(HttpStatus.NO_CONTENT);
230        }
231
232        /**
233         * Assert the response status code is {@code HttpStatus.RESET_CONTENT} (205).
234         */
235        public ResultMatcher isResetContent() {
236                return matcher(HttpStatus.RESET_CONTENT);
237        }
238
239        /**
240         * Assert the response status code is {@code HttpStatus.PARTIAL_CONTENT} (206).
241         */
242        public ResultMatcher isPartialContent() {
243                return matcher(HttpStatus.PARTIAL_CONTENT);
244        }
245
246        /**
247         * Assert the response status code is {@code HttpStatus.MULTI_STATUS} (207).
248         */
249        public ResultMatcher isMultiStatus() {
250                return matcher(HttpStatus.MULTI_STATUS);
251        }
252
253        /**
254         * Assert the response status code is {@code HttpStatus.ALREADY_REPORTED} (208).
255         */
256        public ResultMatcher isAlreadyReported() {
257                return matcher(HttpStatus.ALREADY_REPORTED);
258        }
259
260        /**
261         * Assert the response status code is {@code HttpStatus.IM_USED} (226).
262         */
263        public ResultMatcher isImUsed() {
264                return matcher(HttpStatus.IM_USED);
265        }
266
267        /**
268         * Assert the response status code is {@code HttpStatus.MULTIPLE_CHOICES} (300).
269         */
270        public ResultMatcher isMultipleChoices() {
271                return matcher(HttpStatus.MULTIPLE_CHOICES);
272        }
273
274        /**
275         * Assert the response status code is {@code HttpStatus.MOVED_PERMANENTLY} (301).
276         */
277        public ResultMatcher isMovedPermanently() {
278                return matcher(HttpStatus.MOVED_PERMANENTLY);
279        }
280
281        /**
282         * Assert the response status code is {@code HttpStatus.FOUND} (302).
283         */
284        public ResultMatcher isFound() {
285                return matcher(HttpStatus.FOUND);
286        }
287
288        /**
289         * Assert the response status code is {@code HttpStatus.MOVED_TEMPORARILY} (302).
290         * @see #isFound()
291         * @deprecated in favor of {@link #isFound()}
292         */
293        @Deprecated
294        public ResultMatcher isMovedTemporarily() {
295                return matcher(HttpStatus.MOVED_TEMPORARILY);
296        }
297
298        /**
299         * Assert the response status code is {@code HttpStatus.SEE_OTHER} (303).
300         */
301        public ResultMatcher isSeeOther() {
302                return matcher(HttpStatus.SEE_OTHER);
303        }
304
305        /**
306         * Assert the response status code is {@code HttpStatus.NOT_MODIFIED} (304).
307         */
308        public ResultMatcher isNotModified() {
309                return matcher(HttpStatus.NOT_MODIFIED);
310        }
311
312        /**
313         * Assert the response status code is {@code HttpStatus.USE_PROXY} (305).
314         * @deprecated matching the deprecation of {@code HttpStatus.USE_PROXY}
315         */
316        @Deprecated
317        public ResultMatcher isUseProxy() {
318                return matcher(HttpStatus.USE_PROXY);
319        }
320
321        /**
322         * Assert the response status code is {@code HttpStatus.TEMPORARY_REDIRECT} (307).
323         */
324        public ResultMatcher isTemporaryRedirect() {
325                return matcher(HttpStatus.TEMPORARY_REDIRECT);
326        }
327
328        /**
329         * Assert the response status code is {@code HttpStatus.PERMANENT_REDIRECT} (308).
330         */
331        public ResultMatcher isPermanentRedirect() {
332                return matcher(HttpStatus.valueOf(308));
333        }
334
335        /**
336         * Assert the response status code is {@code HttpStatus.BAD_REQUEST} (400).
337         */
338        public ResultMatcher isBadRequest() {
339                return matcher(HttpStatus.BAD_REQUEST);
340        }
341
342        /**
343         * Assert the response status code is {@code HttpStatus.UNAUTHORIZED} (401).
344         */
345        public ResultMatcher isUnauthorized() {
346                return matcher(HttpStatus.UNAUTHORIZED);
347        }
348
349        /**
350         * Assert the response status code is {@code HttpStatus.PAYMENT_REQUIRED} (402).
351         */
352        public ResultMatcher isPaymentRequired() {
353                return matcher(HttpStatus.PAYMENT_REQUIRED);
354        }
355
356        /**
357         * Assert the response status code is {@code HttpStatus.FORBIDDEN} (403).
358         */
359        public ResultMatcher isForbidden() {
360                return matcher(HttpStatus.FORBIDDEN);
361        }
362
363        /**
364         * Assert the response status code is {@code HttpStatus.NOT_FOUND} (404).
365         */
366        public ResultMatcher isNotFound() {
367                return matcher(HttpStatus.NOT_FOUND);
368        }
369
370        /**
371         * Assert the response status code is {@code HttpStatus.METHOD_NOT_ALLOWED} (405).
372         */
373        public ResultMatcher isMethodNotAllowed() {
374                return matcher(HttpStatus.METHOD_NOT_ALLOWED);
375        }
376
377        /**
378         * Assert the response status code is {@code HttpStatus.NOT_ACCEPTABLE} (406).
379         */
380        public ResultMatcher isNotAcceptable() {
381                return matcher(HttpStatus.NOT_ACCEPTABLE);
382        }
383
384        /**
385         * Assert the response status code is {@code HttpStatus.PROXY_AUTHENTICATION_REQUIRED} (407).
386         */
387        public ResultMatcher isProxyAuthenticationRequired() {
388                return matcher(HttpStatus.PROXY_AUTHENTICATION_REQUIRED);
389        }
390
391        /**
392         * Assert the response status code is {@code HttpStatus.REQUEST_TIMEOUT} (408).
393         */
394        public ResultMatcher isRequestTimeout() {
395                return matcher(HttpStatus.REQUEST_TIMEOUT);
396        }
397
398        /**
399         * Assert the response status code is {@code HttpStatus.CONFLICT} (409).
400         */
401        public ResultMatcher isConflict() {
402                return matcher(HttpStatus.CONFLICT);
403        }
404
405        /**
406         * Assert the response status code is {@code HttpStatus.GONE} (410).
407         */
408        public ResultMatcher isGone() {
409                return matcher(HttpStatus.GONE);
410        }
411
412        /**
413         * Assert the response status code is {@code HttpStatus.LENGTH_REQUIRED} (411).
414         */
415        public ResultMatcher isLengthRequired() {
416                return matcher(HttpStatus.LENGTH_REQUIRED);
417        }
418
419        /**
420         * Assert the response status code is {@code HttpStatus.PRECONDITION_FAILED} (412).
421         */
422        public ResultMatcher isPreconditionFailed() {
423                return matcher(HttpStatus.PRECONDITION_FAILED);
424        }
425
426        /**
427         * Assert the response status code is {@code HttpStatus.PAYLOAD_TOO_LARGE} (413).
428         * @since 4.1
429         */
430        public ResultMatcher isPayloadTooLarge() {
431                return matcher(HttpStatus.PAYLOAD_TOO_LARGE);
432        }
433
434        /**
435         * Assert the response status code is {@code HttpStatus.REQUEST_ENTITY_TOO_LARGE} (413).
436         * @deprecated matching the deprecation of {@code HttpStatus.REQUEST_ENTITY_TOO_LARGE}
437         * @see #isPayloadTooLarge()
438         */
439        @Deprecated
440        public ResultMatcher isRequestEntityTooLarge() {
441                return matcher(HttpStatus.REQUEST_ENTITY_TOO_LARGE);
442        }
443
444        /**
445         * Assert the response status code is {@code HttpStatus.REQUEST_URI_TOO_LONG} (414).
446         * @since 4.1
447         */
448        public ResultMatcher isUriTooLong() {
449                return matcher(HttpStatus.URI_TOO_LONG);
450        }
451
452        /**
453         * Assert the response status code is {@code HttpStatus.REQUEST_URI_TOO_LONG} (414).
454         * @deprecated matching the deprecation of {@code HttpStatus.REQUEST_URI_TOO_LONG}
455         * @see #isUriTooLong()
456         */
457        @Deprecated
458        public ResultMatcher isRequestUriTooLong() {
459                return matcher(HttpStatus.REQUEST_URI_TOO_LONG);
460        }
461
462        /**
463         * Assert the response status code is {@code HttpStatus.UNSUPPORTED_MEDIA_TYPE} (415).
464         */
465        public ResultMatcher isUnsupportedMediaType() {
466                return matcher(HttpStatus.UNSUPPORTED_MEDIA_TYPE);
467        }
468
469        /**
470         * Assert the response status code is {@code HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE} (416).
471         */
472        public ResultMatcher isRequestedRangeNotSatisfiable() {
473                return matcher(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE);
474        }
475
476        /**
477         * Assert the response status code is {@code HttpStatus.EXPECTATION_FAILED} (417).
478         */
479        public ResultMatcher isExpectationFailed() {
480                return matcher(HttpStatus.EXPECTATION_FAILED);
481        }
482
483        /**
484         * Assert the response status code is {@code HttpStatus.I_AM_A_TEAPOT} (418).
485         */
486        public ResultMatcher isIAmATeapot() {
487                return matcher(HttpStatus.valueOf(418));
488        }
489
490        /**
491          * Assert the response status code is {@code HttpStatus.INSUFFICIENT_SPACE_ON_RESOURCE} (419).
492          * @deprecated matching the deprecation of {@code HttpStatus.INSUFFICIENT_SPACE_ON_RESOURCE}
493          */
494         @Deprecated
495         public ResultMatcher isInsufficientSpaceOnResource() {
496                 return matcher(HttpStatus.INSUFFICIENT_SPACE_ON_RESOURCE);
497         }
498
499         /**
500          * Assert the response status code is {@code HttpStatus.METHOD_FAILURE} (420).
501          * @deprecated matching the deprecation of {@code HttpStatus.METHOD_FAILURE}
502          */
503         @Deprecated
504         public ResultMatcher isMethodFailure() {
505                 return matcher(HttpStatus.METHOD_FAILURE);
506         }
507
508         /**
509          * Assert the response status code is {@code HttpStatus.DESTINATION_LOCKED} (421).
510          * @deprecated matching the deprecation of {@code HttpStatus.DESTINATION_LOCKED}
511          */
512         @Deprecated
513         public ResultMatcher isDestinationLocked() {
514                 return matcher(HttpStatus.DESTINATION_LOCKED);
515         }
516
517        /**
518         * Assert the response status code is {@code HttpStatus.UNPROCESSABLE_ENTITY} (422).
519         */
520        public ResultMatcher isUnprocessableEntity() {
521                return matcher(HttpStatus.UNPROCESSABLE_ENTITY);
522        }
523
524        /**
525         * Assert the response status code is {@code HttpStatus.LOCKED} (423).
526         */
527        public ResultMatcher isLocked() {
528                return matcher(HttpStatus.LOCKED);
529        }
530
531        /**
532         * Assert the response status code is {@code HttpStatus.FAILED_DEPENDENCY} (424).
533         */
534        public ResultMatcher isFailedDependency() {
535                return matcher(HttpStatus.FAILED_DEPENDENCY);
536        }
537
538        /**
539         * Assert the response status code is {@code HttpStatus.UPGRADE_REQUIRED} (426).
540         */
541        public ResultMatcher isUpgradeRequired() {
542                return matcher(HttpStatus.UPGRADE_REQUIRED);
543        }
544
545        /**
546         * Assert the response status code is {@code HttpStatus.PRECONDITION_REQUIRED} (428).
547         */
548        public ResultMatcher isPreconditionRequired() {
549                return matcher(HttpStatus.valueOf(428));
550        }
551
552        /**
553         * Assert the response status code is {@code HttpStatus.TOO_MANY_REQUESTS} (429).
554         */
555        public ResultMatcher isTooManyRequests() {
556                return matcher(HttpStatus.valueOf(429));
557        }
558
559        /**
560         * Assert the response status code is {@code HttpStatus.REQUEST_HEADER_FIELDS_TOO_LARGE} (431).
561         */
562        public ResultMatcher isRequestHeaderFieldsTooLarge() {
563                return matcher(HttpStatus.valueOf(431));
564        }
565
566        /**
567         * Assert the response status code is {@code HttpStatus.UNAVAILABLE_FOR_LEGAL_REASONS} (451).
568         * @since 4.3
569         */
570        public ResultMatcher isUnavailableForLegalReasons() {
571                return matcher(HttpStatus.valueOf(451));
572        }
573
574        /**
575         * Assert the response status code is {@code HttpStatus.INTERNAL_SERVER_ERROR} (500).
576         */
577        public ResultMatcher isInternalServerError() {
578                return matcher(HttpStatus.INTERNAL_SERVER_ERROR);
579        }
580
581        /**
582         * Assert the response status code is {@code HttpStatus.NOT_IMPLEMENTED} (501).
583         */
584        public ResultMatcher isNotImplemented() {
585                return matcher(HttpStatus.NOT_IMPLEMENTED);
586        }
587
588        /**
589         * Assert the response status code is {@code HttpStatus.BAD_GATEWAY} (502).
590         */
591        public ResultMatcher isBadGateway() {
592                return matcher(HttpStatus.BAD_GATEWAY);
593        }
594
595        /**
596         * Assert the response status code is {@code HttpStatus.SERVICE_UNAVAILABLE} (503).
597         */
598        public ResultMatcher isServiceUnavailable() {
599                return matcher(HttpStatus.SERVICE_UNAVAILABLE);
600        }
601
602        /**
603         * Assert the response status code is {@code HttpStatus.GATEWAY_TIMEOUT} (504).
604         */
605        public ResultMatcher isGatewayTimeout() {
606                return matcher(HttpStatus.GATEWAY_TIMEOUT);
607        }
608
609        /**
610         * Assert the response status code is {@code HttpStatus.HTTP_VERSION_NOT_SUPPORTED} (505).
611         */
612        public ResultMatcher isHttpVersionNotSupported() {
613                return matcher(HttpStatus.HTTP_VERSION_NOT_SUPPORTED);
614        }
615
616        /**
617         * Assert the response status code is {@code HttpStatus.VARIANT_ALSO_NEGOTIATES} (506).
618         */
619        public ResultMatcher isVariantAlsoNegotiates() {
620                return matcher(HttpStatus.VARIANT_ALSO_NEGOTIATES);
621        }
622
623        /**
624         * Assert the response status code is {@code HttpStatus.INSUFFICIENT_STORAGE} (507).
625         */
626        public ResultMatcher isInsufficientStorage() {
627                return matcher(HttpStatus.INSUFFICIENT_STORAGE);
628        }
629
630        /**
631         * Assert the response status code is {@code HttpStatus.LOOP_DETECTED} (508).
632         */
633        public ResultMatcher isLoopDetected() {
634                return matcher(HttpStatus.LOOP_DETECTED);
635        }
636
637        /**
638         * Assert the response status code is {@code HttpStatus.BANDWIDTH_LIMIT_EXCEEDED} (509).
639         */
640        public ResultMatcher isBandwidthLimitExceeded() {
641                return matcher(HttpStatus.valueOf(509));
642        }
643
644        /**
645         * Assert the response status code is {@code HttpStatus.NOT_EXTENDED} (510).
646         */
647        public ResultMatcher isNotExtended() {
648                return matcher(HttpStatus.NOT_EXTENDED);
649        }
650
651        /**
652         * Assert the response status code is {@code HttpStatus.NETWORK_AUTHENTICATION_REQUIRED} (511).
653         */
654        public ResultMatcher isNetworkAuthenticationRequired() {
655                return matcher(HttpStatus.valueOf(511));
656        }
657
658        /**
659         * Match the expected response status to that of the HttpServletResponse
660         */
661        private ResultMatcher matcher(final HttpStatus status) {
662                return new ResultMatcher() {
663                        @Override
664                        public void match(MvcResult result) {
665                                assertEquals("Status", status.value(), result.getResponse().getStatus());
666                        }
667                };
668        }
669
670}