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