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