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 java.util.concurrent.Callable;
020import javax.servlet.http.HttpServletRequest;
021
022import org.hamcrest.Matcher;
023
024import org.springframework.mock.web.MockHttpServletRequest;
025import org.springframework.test.web.servlet.MvcResult;
026import org.springframework.test.web.servlet.ResultMatcher;
027import org.springframework.web.context.request.async.DeferredResult;
028import org.springframework.web.context.request.async.WebAsyncTask;
029
030import static org.hamcrest.MatcherAssert.*;
031import static org.springframework.test.util.AssertionErrors.*;
032
033/**
034 * Factory for assertions on the request.
035 *
036 * <p>An instance of this class is typically accessed via
037 * {@link MockMvcResultMatchers#request}.
038 *
039 * @author Rossen Stoyanchev
040 * @author Sam Brannen
041 * @since 3.2
042 */
043public class RequestResultMatchers {
044
045        /**
046         * Protected constructor.
047         * <p>Use {@link MockMvcResultMatchers#request()}.
048         */
049        protected RequestResultMatchers() {
050        }
051
052
053        /**
054         * Assert whether asynchronous processing started, usually as a result of a
055         * controller method returning {@link Callable} or {@link DeferredResult}.
056         * <p>The test will await the completion of a {@code Callable} so that
057         * {@link #asyncResult(Matcher)} can be used to assert the resulting value.
058         * Neither a {@code Callable} nor a {@code DeferredResult} will complete
059         * processing all the way since a {@link MockHttpServletRequest} does not
060         * perform asynchronous dispatches.
061         */
062        public ResultMatcher asyncStarted() {
063                return new ResultMatcher() {
064                        @Override
065                        public void match(MvcResult result) {
066                                HttpServletRequest request = result.getRequest();
067                                assertAsyncStarted(request);
068                        }
069                };
070        }
071
072        /**
073         * Assert that asynchronous processing was not started.
074         * @see #asyncStarted()
075         */
076        public ResultMatcher asyncNotStarted() {
077                return new ResultMatcher() {
078                        @Override
079                        public void match(MvcResult result) {
080                                HttpServletRequest request = result.getRequest();
081                                assertEquals("Async started", false, request.isAsyncStarted());
082                        }
083                };
084        }
085
086        /**
087         * Assert the result from asynchronous processing with the given matcher.
088         * <p>This method can be used when a controller method returns {@link Callable}
089         * or {@link WebAsyncTask}.
090         */
091        public <T> ResultMatcher asyncResult(final Matcher<T> matcher) {
092                return new ResultMatcher() {
093                        @Override
094                        @SuppressWarnings("unchecked")
095                        public void match(MvcResult result) {
096                                HttpServletRequest request = result.getRequest();
097                                assertAsyncStarted(request);
098                                assertThat("Async result", (T) result.getAsyncResult(), matcher);
099                        }
100                };
101        }
102
103        /**
104         * Assert the result from asynchronous processing.
105         * <p>This method can be used when a controller method returns {@link Callable}
106         * or {@link WebAsyncTask}. The value matched is the value returned from the
107         * {@code Callable} or the exception raised.
108         */
109        public <T> ResultMatcher asyncResult(final Object expectedResult) {
110                return new ResultMatcher() {
111                        @Override
112                        public void match(MvcResult result) {
113                                HttpServletRequest request = result.getRequest();
114                                assertAsyncStarted(request);
115                                assertEquals("Async result", expectedResult, result.getAsyncResult());
116                        }
117                };
118        }
119
120        /**
121         * Assert a request attribute value with the given Hamcrest {@link Matcher}.
122         */
123        public <T> ResultMatcher attribute(final String name, final Matcher<T> matcher) {
124                return new ResultMatcher() {
125                        @Override
126                        @SuppressWarnings("unchecked")
127                        public void match(MvcResult result) {
128                                T value = (T) result.getRequest().getAttribute(name);
129                                assertThat("Request attribute '" + name + "'", value, matcher);
130                        }
131                };
132        }
133
134        /**
135         * Assert a request attribute value.
136         */
137        public <T> ResultMatcher attribute(final String name, final Object expectedValue) {
138                return new ResultMatcher() {
139                        @Override
140                        public void match(MvcResult result) {
141                                assertEquals("Request attribute '" + name + "'", expectedValue, result.getRequest().getAttribute(name));
142                        }
143                };
144        }
145
146        /**
147         * Assert a session attribute value with the given Hamcrest {@link Matcher}.
148         */
149        public <T> ResultMatcher sessionAttribute(final String name, final Matcher<T> matcher) {
150                return new ResultMatcher() {
151                        @Override
152                        @SuppressWarnings("unchecked")
153                        public void match(MvcResult result) {
154                                T value = (T) result.getRequest().getSession().getAttribute(name);
155                                assertThat("Session attribute '" + name + "'", value, matcher);
156                        }
157                };
158        }
159
160        /**
161         * Assert a session attribute value.
162         */
163        public <T> ResultMatcher sessionAttribute(final String name, final Object value) {
164                return new ResultMatcher() {
165                        @Override
166                        public void match(MvcResult result) {
167                                assertEquals("Session attribute '" + name + "'", value, result.getRequest().getSession().getAttribute(name));
168                        }
169                };
170        }
171
172        private static void assertAsyncStarted(HttpServletRequest request) {
173                assertEquals("Async started", true, request.isAsyncStarted());
174        }
175
176}