Add support for fluent preparation of the request in MockMvcTester
See gh-32913
This commit is contained in:
parent
a3e7fd47c6
commit
8d2bc3bdba
|
|
@ -23,13 +23,18 @@ import java.util.Map;
|
|||
import java.util.function.Function;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import org.assertj.core.api.AssertProvider;
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.GenericHttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.RequestBuilder;
|
||||
import org.springframework.test.web.servlet.request.AbstractMockHttpServletRequestBuilder;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
import org.springframework.test.web.servlet.setup.DefaultMockMvcBuilder;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
|
|
@ -58,11 +63,25 @@ import org.springframework.web.context.WebApplicationContext;
|
|||
* MockMvcTester mvc = MockMvcTester.of(new PersonController());
|
||||
* </code></pre>
|
||||
*
|
||||
* <p>Once a tester instance is available, you can perform requests in a similar
|
||||
* fashion as with {@link MockMvc}, and wrapping the result in
|
||||
* {@code assertThat()} provides access to assertions. For instance:
|
||||
* <p>Simple, single-statement assertions can be done wrapping the request
|
||||
* builder in {@code assertThat()} provides access to assertions. For instance:
|
||||
* <pre><code class="java">
|
||||
* // perform a GET on /hi and assert the response body is equal to Hello
|
||||
* assertThat(mvc.get().uri("/hi")).hasStatusOk().hasBodyTextEqualTo("Hello");
|
||||
* </code></pre>
|
||||
*
|
||||
*<p>For more complex scenarios the {@linkplain MvcTestResult result} of the
|
||||
* exchange can be assigned in a variable to run multiple assertions:
|
||||
* <pre><code class="java">
|
||||
* // perform a POST on /save and assert the response body is empty
|
||||
* MvcTestResult result = mvc.post().uri("/save").exchange();
|
||||
* assertThat(result).hasStatus(HttpStatus.CREATED);
|
||||
* assertThat(result).body().isEmpty();
|
||||
* </code></pre>
|
||||
*
|
||||
* <p>You can also perform requests using the static builders approach that
|
||||
* {@link MockMvc} uses. For instance:<pre><code class="java">
|
||||
* // perform a GET on /hi and assert the response body is equal to Hello
|
||||
* assertThat(mvc.perform(get("/hi")))
|
||||
* .hasStatusOk().hasBodyTextEqualTo("Hello");
|
||||
* </code></pre>
|
||||
|
|
@ -74,12 +93,11 @@ import org.springframework.web.context.WebApplicationContext;
|
|||
* which allows you to assert that a request failed unexpectedly:
|
||||
* <pre><code class="java">
|
||||
* // perform a GET on /boom and assert the message for the the unresolved exception
|
||||
* assertThat(mvc.perform(get("/boom")))
|
||||
* .hasUnresolvedException())
|
||||
* assertThat(mvc.get().uri("/boom")).hasUnresolvedException())
|
||||
* .withMessage("Test exception");
|
||||
* </code></pre>
|
||||
*
|
||||
* <p>{@link MockMvcTester} can be configured with a list of
|
||||
* <p>{@code MockMvcTester} can be configured with a list of
|
||||
* {@linkplain HttpMessageConverter message converters} to allow the response
|
||||
* body to be deserialized, rather than asserting on the raw values.
|
||||
*
|
||||
|
|
@ -104,8 +122,7 @@ public final class MockMvcTester {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create a {@link MockMvcTester} instance that delegates to the given
|
||||
* {@link MockMvc} instance.
|
||||
* Create an instance that delegates to the given {@link MockMvc} instance.
|
||||
* @param mockMvc the MockMvc instance to delegate calls to
|
||||
*/
|
||||
public static MockMvcTester create(MockMvc mockMvc) {
|
||||
|
|
@ -113,9 +130,9 @@ public final class MockMvcTester {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create an {@link MockMvcTester} instance using the given, fully
|
||||
* initialized (i.e., <em>refreshed</em>) {@link WebApplicationContext}. The
|
||||
* given {@code customizations} are applied to the {@link DefaultMockMvcBuilder}
|
||||
* Create an instance using the given, fully initialized (i.e.,
|
||||
* <em>refreshed</em>) {@link WebApplicationContext}. The given
|
||||
* {@code customizations} are applied to the {@link DefaultMockMvcBuilder}
|
||||
* that ultimately creates the underlying {@link MockMvc} instance.
|
||||
* <p>If no further customization of the underlying {@link MockMvc} instance
|
||||
* is required, use {@link #from(WebApplicationContext)}.
|
||||
|
|
@ -134,8 +151,8 @@ public final class MockMvcTester {
|
|||
}
|
||||
|
||||
/**
|
||||
* Shortcut to create an {@link MockMvcTester} instance using the given,
|
||||
* fully initialized (i.e., <em>refreshed</em>) {@link WebApplicationContext}.
|
||||
* Shortcut to create an instance using the given fully initialized (i.e.,
|
||||
* <em>refreshed</em>) {@link WebApplicationContext}.
|
||||
* <p>Consider using {@link #from(WebApplicationContext, Function)} if
|
||||
* further customization of the underlying {@link MockMvc} instance is
|
||||
* required.
|
||||
|
|
@ -148,9 +165,8 @@ public final class MockMvcTester {
|
|||
}
|
||||
|
||||
/**
|
||||
* Create an {@link MockMvcTester} instance by registering one or more
|
||||
* {@code @Controller} instances and configuring Spring MVC infrastructure
|
||||
* programmatically.
|
||||
* Create an instance by registering one or more {@code @Controller} instances
|
||||
* and configuring Spring MVC infrastructure programmatically.
|
||||
* <p>This allows full control over the instantiation and initialization of
|
||||
* controllers and their dependencies, similar to plain unit tests while
|
||||
* also making it possible to test one controller at a time.
|
||||
|
|
@ -170,8 +186,8 @@ public final class MockMvcTester {
|
|||
}
|
||||
|
||||
/**
|
||||
* Shortcut to create an {@link MockMvcTester} instance by registering one
|
||||
* or more {@code @Controller} instances.
|
||||
* Shortcut to create an instance by registering one or more {@code @Controller}
|
||||
* instances.
|
||||
* <p>The minimum infrastructure required by the
|
||||
* {@link org.springframework.web.servlet.DispatcherServlet DispatcherServlet}
|
||||
* to serve requests with annotated controllers is created. Consider using
|
||||
|
|
@ -187,8 +203,8 @@ public final class MockMvcTester {
|
|||
}
|
||||
|
||||
/**
|
||||
* Return a new {@link MockMvcTester} instance using the specified
|
||||
* {@linkplain HttpMessageConverter message converters}.
|
||||
* Return a new instance using the specified {@linkplain HttpMessageConverter
|
||||
* message converters}.
|
||||
* <p>If none are specified, only basic assertions on the response body can
|
||||
* be performed. Consider registering a suitable JSON converter for asserting
|
||||
* against JSON data structures.
|
||||
|
|
@ -200,8 +216,105 @@ public final class MockMvcTester {
|
|||
}
|
||||
|
||||
/**
|
||||
* Perform a request and return a {@link MvcTestResult result} that can be
|
||||
* used with standard {@link org.assertj.core.api.Assertions AssertJ} assertions.
|
||||
* Prepare an HTTP GET request.
|
||||
* <p>The returned builder can be wrapped in {@code assertThat} to enable
|
||||
* assertions on the result. For multi-statements assertions, use
|
||||
* {@linkplain MockMvcRequestBuilder#exchange() exchange} to assign the
|
||||
* result.
|
||||
* @return a request builder for specifying the target URI
|
||||
*/
|
||||
public MockMvcRequestBuilder get() {
|
||||
return method(HttpMethod.GET);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare an HTTP HEAD request.
|
||||
* <p>The returned builder can be wrapped in {@code assertThat} to enable
|
||||
* assertions on the result. For multi-statements assertions, use
|
||||
* {@linkplain MockMvcRequestBuilder#exchange() exchange} to assign the
|
||||
* result.
|
||||
* @return a request builder for specifying the target URI
|
||||
*/
|
||||
public MockMvcRequestBuilder head() {
|
||||
return method(HttpMethod.HEAD);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare an HTTP POST request.
|
||||
* <p>The returned builder can be wrapped in {@code assertThat} to enable
|
||||
* assertions on the result. For multi-statements assertions, use
|
||||
* {@linkplain MockMvcRequestBuilder#exchange() exchange} to assign the
|
||||
* result.
|
||||
* @return a request builder for specifying the target URI
|
||||
*/
|
||||
public MockMvcRequestBuilder post() {
|
||||
return method(HttpMethod.POST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare an HTTP PUT request.
|
||||
* <p>The returned builder can be wrapped in {@code assertThat} to enable
|
||||
* assertions on the result. For multi-statements assertions, use
|
||||
* {@linkplain MockMvcRequestBuilder#exchange() exchange} to assign the
|
||||
* result.
|
||||
* @return a request builder for specifying the target URI
|
||||
*/
|
||||
public MockMvcRequestBuilder put() {
|
||||
return method(HttpMethod.PUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare an HTTP PATCH request.
|
||||
* <p>The returned builder can be wrapped in {@code assertThat} to enable
|
||||
* assertions on the result. For multi-statements assertions, use
|
||||
* {@linkplain MockMvcRequestBuilder#exchange() exchange} to assign the
|
||||
* result.
|
||||
* @return a request builder for specifying the target URI
|
||||
*/
|
||||
public MockMvcRequestBuilder patch() {
|
||||
return method(HttpMethod.PATCH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare an HTTP DELETE request.
|
||||
* <p>The returned builder can be wrapped in {@code assertThat} to enable
|
||||
* assertions on the result. For multi-statements assertions, use
|
||||
* {@linkplain MockMvcRequestBuilder#exchange() exchange} to assign the
|
||||
* result.
|
||||
* @return a request builder for specifying the target URI
|
||||
*/
|
||||
public MockMvcRequestBuilder delete() {
|
||||
return method(HttpMethod.DELETE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare an HTTP OPTIONS request.
|
||||
* <p>The returned builder can be wrapped in {@code assertThat} to enable
|
||||
* assertions on the result. For multi-statements assertions, use
|
||||
* {@linkplain MockMvcRequestBuilder#exchange() exchange} to assign the
|
||||
* result.
|
||||
* @return a request builder for specifying the target URI
|
||||
*/
|
||||
public MockMvcRequestBuilder options() {
|
||||
return method(HttpMethod.OPTIONS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a request for the specified {@code HttpMethod}.
|
||||
* <p>The returned builder can be wrapped in {@code assertThat} to enable
|
||||
* assertions on the result. For multi-statements assertions, use
|
||||
* {@linkplain MockMvcRequestBuilder#exchange() exchange} to assign the
|
||||
* result.
|
||||
* @return a request builder for specifying the target URI
|
||||
*/
|
||||
public MockMvcRequestBuilder method(HttpMethod method) {
|
||||
return new MockMvcRequestBuilder(method);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a request using {@link MockMvcRequestBuilders} and return a
|
||||
* {@link MvcTestResult result} that can be used with standard
|
||||
* {@link org.assertj.core.api.Assertions AssertJ} assertions.
|
||||
* <p>Use static methods of {@link MockMvcRequestBuilders} to prepare the
|
||||
* request, wrapping the invocation in {@code assertThat}. The following
|
||||
* asserts that a {@linkplain MockMvcRequestBuilders#get(URI) GET} request
|
||||
|
|
@ -226,6 +339,8 @@ public final class MockMvcTester {
|
|||
* {@link org.springframework.test.web.servlet.request.MockMvcRequestBuilders}
|
||||
* @return an {@link MvcTestResult} to be wrapped in {@code assertThat}
|
||||
* @see MockMvc#perform(RequestBuilder)
|
||||
* @see #get()
|
||||
* @see #post()
|
||||
*/
|
||||
public MvcTestResult perform(RequestBuilder requestBuilder) {
|
||||
Object result = getMvcResultOrFailure(requestBuilder);
|
||||
|
|
@ -259,4 +374,25 @@ public final class MockMvcTester {
|
|||
.findFirst().orElse(null);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A builder for {@link MockHttpServletRequest} that supports AssertJ.
|
||||
*/
|
||||
public final class MockMvcRequestBuilder extends AbstractMockHttpServletRequestBuilder<MockMvcRequestBuilder>
|
||||
implements AssertProvider<MvcTestResultAssert> {
|
||||
|
||||
private MockMvcRequestBuilder(HttpMethod httpMethod) {
|
||||
super(httpMethod);
|
||||
}
|
||||
|
||||
public MvcTestResult exchange() {
|
||||
return perform(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MvcTestResultAssert assertThat() {
|
||||
return new MvcTestResultAssert(exchange(), MockMvcTester.this.jsonMessageConverter);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.test.web.servlet.assertj;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link MockMvcTester} that use the methods that
|
||||
* integrate with {@link MockMvc} way of building the requests and
|
||||
* asserting the responses.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@SpringJUnitConfig
|
||||
@WebAppConfiguration
|
||||
class MockMvcTesterCompatibilityIntegrationTests {
|
||||
|
||||
private final MockMvcTester mvc;
|
||||
|
||||
MockMvcTesterCompatibilityIntegrationTests(@Autowired WebApplicationContext wac) {
|
||||
this.mvc = MockMvcTester.from(wac);
|
||||
}
|
||||
|
||||
@Test
|
||||
void performGet() {
|
||||
assertThat(this.mvc.perform(get("/greet"))).hasStatusOk();
|
||||
}
|
||||
|
||||
@Test
|
||||
void performGetWithInvalidMediaTypeAssertion() {
|
||||
MvcTestResult result = this.mvc.perform(get("/greet"));
|
||||
assertThatExceptionOfType(AssertionError.class)
|
||||
.isThrownBy(() -> assertThat(result).hasContentTypeCompatibleWith(MediaType.APPLICATION_JSON))
|
||||
.withMessageContaining("is compatible with 'application/json'");
|
||||
}
|
||||
|
||||
@Test
|
||||
void assertHttpStatusCode() {
|
||||
assertThat(this.mvc.get().uri("/greet")).matches(status().isOk());
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
@Import(TestController.class)
|
||||
static class WebConfiguration {
|
||||
}
|
||||
|
||||
@RestController
|
||||
static class TestController {
|
||||
|
||||
@GetMapping(path = "/greet", produces = "text/plain")
|
||||
String greet() {
|
||||
return "hello";
|
||||
}
|
||||
|
||||
@GetMapping(path = "/message", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
String message() {
|
||||
return "{\"message\": \"hello\"}";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -43,7 +43,7 @@ import org.springframework.stereotype.Controller;
|
|||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.test.web.Person;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.springframework.test.web.servlet.ResultMatcher;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
|
@ -63,9 +63,8 @@ import static java.util.Map.entry;
|
|||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.InstanceOfAssertFactories.map;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link MockMvcTester}.
|
||||
|
|
@ -77,10 +76,10 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
|
|||
@WebAppConfiguration
|
||||
public class MockMvcTesterIntegrationTests {
|
||||
|
||||
private final MockMvcTester mockMvc;
|
||||
private final MockMvcTester mvc;
|
||||
|
||||
MockMvcTesterIntegrationTests(WebApplicationContext wac) {
|
||||
this.mockMvc = MockMvcTester.from(wac);
|
||||
this.mvc = MockMvcTester.from(wac);
|
||||
}
|
||||
|
||||
@Nested
|
||||
|
|
@ -88,24 +87,24 @@ public class MockMvcTesterIntegrationTests {
|
|||
|
||||
@Test
|
||||
void hasAsyncStartedTrue() {
|
||||
assertThat(perform(get("/callable").accept(MediaType.APPLICATION_JSON)))
|
||||
assertThat(mvc.get().uri("/callable").accept(MediaType.APPLICATION_JSON))
|
||||
.request().hasAsyncStarted(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
void hasAsyncStartedFalse() {
|
||||
assertThat(perform(get("/greet"))).request().hasAsyncStarted(false);
|
||||
assertThat(mvc.get().uri("/greet")).request().hasAsyncStarted(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
void attributes() {
|
||||
assertThat(perform(get("/greet"))).request().attributes()
|
||||
assertThat(mvc.get().uri("/greet")).request().attributes()
|
||||
.containsKey(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE);
|
||||
}
|
||||
|
||||
@Test
|
||||
void sessionAttributes() {
|
||||
assertThat(perform(get("/locale"))).request().sessionAttributes()
|
||||
assertThat(mvc.get().uri("/locale")).request().sessionAttributes()
|
||||
.containsOnly(entry("locale", Locale.UK));
|
||||
}
|
||||
}
|
||||
|
|
@ -116,17 +115,17 @@ public class MockMvcTesterIntegrationTests {
|
|||
@Test
|
||||
void containsCookie() {
|
||||
Cookie cookie = new Cookie("test", "value");
|
||||
assertThat(performWithCookie(cookie, get("/greet"))).cookies().containsCookie("test");
|
||||
assertThat(withCookie(cookie).get().uri("/greet")).cookies().containsCookie("test");
|
||||
}
|
||||
|
||||
@Test
|
||||
void hasValue() {
|
||||
Cookie cookie = new Cookie("test", "value");
|
||||
assertThat(performWithCookie(cookie, get("/greet"))).cookies().hasValue("test", "value");
|
||||
assertThat(withCookie(cookie).get().uri("/greet")).cookies().hasValue("test", "value");
|
||||
}
|
||||
|
||||
private MvcTestResult performWithCookie(Cookie cookie, MockHttpServletRequestBuilder request) {
|
||||
MockMvcTester mockMvc = MockMvcTester.of(List.of(new TestController()), builder -> builder.addInterceptors(
|
||||
private MockMvcTester withCookie(Cookie cookie) {
|
||||
return MockMvcTester.of(List.of(new TestController()), builder -> builder.addInterceptors(
|
||||
new HandlerInterceptor() {
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
|
||||
|
|
@ -134,7 +133,6 @@ public class MockMvcTesterIntegrationTests {
|
|||
return true;
|
||||
}
|
||||
}).build());
|
||||
return mockMvc.perform(request);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -143,12 +141,12 @@ public class MockMvcTesterIntegrationTests {
|
|||
|
||||
@Test
|
||||
void statusOk() {
|
||||
assertThat(perform(get("/greet"))).hasStatusOk();
|
||||
assertThat(mvc.get().uri("/greet")).hasStatusOk();
|
||||
}
|
||||
|
||||
@Test
|
||||
void statusSeries() {
|
||||
assertThat(perform(get("/greet"))).hasStatus2xxSuccessful();
|
||||
assertThat(mvc.get().uri("/greet")).hasStatus2xxSuccessful();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -158,13 +156,13 @@ public class MockMvcTesterIntegrationTests {
|
|||
|
||||
@Test
|
||||
void shouldAssertHeader() {
|
||||
assertThat(perform(get("/greet")))
|
||||
assertThat(mvc.get().uri("/greet"))
|
||||
.hasHeader("Content-Type", "text/plain;charset=ISO-8859-1");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldAssertHeaderWithCallback() {
|
||||
assertThat(perform(get("/greet"))).headers().satisfies(textContent("ISO-8859-1"));
|
||||
assertThat(mvc.get().uri("/greet")).headers().satisfies(textContent("ISO-8859-1"));
|
||||
}
|
||||
|
||||
private Consumer<HttpHeaders> textContent(String charset) {
|
||||
|
|
@ -179,33 +177,33 @@ public class MockMvcTesterIntegrationTests {
|
|||
|
||||
@Test
|
||||
void hasViewName() {
|
||||
assertThat(perform(get("/persons/{0}", "Andy"))).hasViewName("persons/index");
|
||||
assertThat(mvc.get().uri("/persons/{0}", "Andy")).hasViewName("persons/index");
|
||||
}
|
||||
|
||||
@Test
|
||||
void viewNameWithCustomAssertion() {
|
||||
assertThat(perform(get("/persons/{0}", "Andy"))).viewName().startsWith("persons");
|
||||
assertThat(mvc.get().uri("/persons/{0}", "Andy")).viewName().startsWith("persons");
|
||||
}
|
||||
|
||||
@Test
|
||||
void containsAttributes() {
|
||||
assertThat(perform(post("/persons").param("name", "Andy"))).model()
|
||||
assertThat(mvc.post().uri("/persons").param("name", "Andy")).model()
|
||||
.containsOnlyKeys("name").containsEntry("name", "Andy");
|
||||
}
|
||||
|
||||
@Test
|
||||
void hasErrors() {
|
||||
assertThat(perform(post("/persons"))).model().hasErrors();
|
||||
assertThat(mvc.post().uri("/persons")).model().hasErrors();
|
||||
}
|
||||
|
||||
@Test
|
||||
void hasAttributeErrors() {
|
||||
assertThat(perform(post("/persons"))).model().hasAttributeErrors("person");
|
||||
assertThat(mvc.post().uri("/persons")).model().hasAttributeErrors("person");
|
||||
}
|
||||
|
||||
@Test
|
||||
void hasAttributeErrorsCount() {
|
||||
assertThat(perform(post("/persons"))).model().extractingBindingResult("person").hasErrorsCount(1);
|
||||
assertThat(mvc.post().uri("/persons")).model().extractingBindingResult("person").hasErrorsCount(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -215,7 +213,7 @@ public class MockMvcTesterIntegrationTests {
|
|||
|
||||
@Test
|
||||
void containsAttributes() {
|
||||
assertThat(perform(post("/persons").param("name", "Andy"))).flash()
|
||||
assertThat(mvc.post().uri("/persons").param("name", "Andy")).flash()
|
||||
.containsOnlyKeys("message").hasEntrySatisfying("message",
|
||||
value -> assertThat(value).isInstanceOfSatisfying(String.class,
|
||||
stringValue -> assertThat(stringValue).startsWith("success")));
|
||||
|
|
@ -227,31 +225,31 @@ public class MockMvcTesterIntegrationTests {
|
|||
|
||||
@Test
|
||||
void asyncResult() {
|
||||
assertThat(perform(get("/callable").accept(MediaType.APPLICATION_JSON)))
|
||||
assertThat(mvc.get().uri("/callable").accept(MediaType.APPLICATION_JSON))
|
||||
.asyncResult().asInstanceOf(map(String.class, Object.class))
|
||||
.containsOnly(entry("key", "value"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void stringContent() {
|
||||
assertThat(perform(get("/greet"))).body().asString().isEqualTo("hello");
|
||||
assertThat(mvc.get().uri("/greet")).body().asString().isEqualTo("hello");
|
||||
}
|
||||
|
||||
@Test
|
||||
void jsonPathContent() {
|
||||
assertThat(perform(get("/message"))).bodyJson()
|
||||
assertThat(mvc.get().uri("/message")).bodyJson()
|
||||
.extractingPath("$.message").asString().isEqualTo("hello");
|
||||
}
|
||||
|
||||
@Test
|
||||
void jsonContentCanLoadResourceFromClasspath() {
|
||||
assertThat(perform(get("/message"))).bodyJson().isLenientlyEqualTo(
|
||||
assertThat(mvc.get().uri("/message")).bodyJson().isLenientlyEqualTo(
|
||||
new ClassPathResource("message.json", MockMvcTesterIntegrationTests.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void jsonContentUsingResourceLoaderClass() {
|
||||
assertThat(perform(get("/message"))).bodyJson().withResourceLoadClass(MockMvcTesterIntegrationTests.class)
|
||||
assertThat(mvc.get().uri("/message")).bodyJson().withResourceLoadClass(MockMvcTesterIntegrationTests.class)
|
||||
.isLenientlyEqualTo("message.json");
|
||||
}
|
||||
|
||||
|
|
@ -262,22 +260,22 @@ public class MockMvcTesterIntegrationTests {
|
|||
|
||||
@Test
|
||||
void handlerOn404() {
|
||||
assertThat(perform(get("/unknown-resource"))).handler().isNull();
|
||||
assertThat(mvc.get().uri("/unknown-resource")).handler().isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void hasType() {
|
||||
assertThat(perform(get("/greet"))).handler().hasType(TestController.class);
|
||||
assertThat(mvc.get().uri("/greet")).handler().hasType(TestController.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void isMethodHandler() {
|
||||
assertThat(perform(get("/greet"))).handler().isMethodHandler();
|
||||
assertThat(mvc.get().uri("/greet")).handler().isMethodHandler();
|
||||
}
|
||||
|
||||
@Test
|
||||
void isInvokedOn() {
|
||||
assertThat(perform(get("/callable"))).handler()
|
||||
assertThat(mvc.get().uri("/callable")).handler()
|
||||
.isInvokedOn(AsyncController.class, AsyncController::getCallable);
|
||||
}
|
||||
|
||||
|
|
@ -288,31 +286,31 @@ public class MockMvcTesterIntegrationTests {
|
|||
|
||||
@Test
|
||||
void doesNotHaveUnresolvedException() {
|
||||
assertThat(perform(get("/greet"))).doesNotHaveUnresolvedException();
|
||||
assertThat(mvc.get().uri("/greet")).doesNotHaveUnresolvedException();
|
||||
}
|
||||
|
||||
@Test
|
||||
void hasUnresolvedException() {
|
||||
assertThat(perform(get("/error/1"))).hasUnresolvedException();
|
||||
assertThat(mvc.get().uri("/error/1")).hasUnresolvedException();
|
||||
}
|
||||
|
||||
@Test
|
||||
void doesNotHaveUnresolvedExceptionWithUnresolvedException() {
|
||||
assertThatExceptionOfType(AssertionError.class)
|
||||
.isThrownBy(() -> assertThat(perform(get("/error/1"))).doesNotHaveUnresolvedException())
|
||||
.isThrownBy(() -> assertThat(mvc.get().uri("/error/1")).doesNotHaveUnresolvedException())
|
||||
.withMessage("Expected request to succeed, but it failed");
|
||||
}
|
||||
|
||||
@Test
|
||||
void hasUnresolvedExceptionWithoutUnresolvedException() {
|
||||
assertThatExceptionOfType(AssertionError.class)
|
||||
.isThrownBy(() -> assertThat(perform(get("/greet"))).hasUnresolvedException())
|
||||
.isThrownBy(() -> assertThat(mvc.get().uri("/greet")).hasUnresolvedException())
|
||||
.withMessage("Expected request to fail, but it succeeded");
|
||||
}
|
||||
|
||||
@Test
|
||||
void unresolvedExceptionWithFailedRequest() {
|
||||
assertThat(perform(get("/error/1"))).unresolvedException()
|
||||
assertThat(mvc.get().uri("/error/1")).unresolvedException()
|
||||
.isInstanceOf(ServletException.class)
|
||||
.cause().isInstanceOf(IllegalStateException.class).hasMessage("Expected");
|
||||
}
|
||||
|
|
@ -320,7 +318,7 @@ public class MockMvcTesterIntegrationTests {
|
|||
@Test
|
||||
void unresolvedExceptionWithSuccessfulRequest() {
|
||||
assertThatExceptionOfType(AssertionError.class)
|
||||
.isThrownBy(() -> assertThat(perform(get("/greet"))).unresolvedException())
|
||||
.isThrownBy(() -> assertThat(mvc.get().uri("/greet")).unresolvedException())
|
||||
.withMessage("Expected request to fail, but it succeeded");
|
||||
}
|
||||
|
||||
|
|
@ -406,7 +404,7 @@ public class MockMvcTesterIntegrationTests {
|
|||
|
||||
|
||||
private void testAssertionFailureWithUnresolvableException(Consumer<MvcTestResult> assertions) {
|
||||
MvcTestResult result = perform(get("/error/1"));
|
||||
MvcTestResult result = mvc.get().uri("/error/1").exchange();
|
||||
assertThatExceptionOfType(AssertionError.class)
|
||||
.isThrownBy(() -> assertions.accept(result))
|
||||
.withMessageContainingAll("Request failed unexpectedly:",
|
||||
|
|
@ -418,49 +416,49 @@ public class MockMvcTesterIntegrationTests {
|
|||
|
||||
@Test
|
||||
void hasForwardUrl() {
|
||||
assertThat(perform(get("/persons/John"))).hasForwardedUrl("persons/index");
|
||||
assertThat(mvc.get().uri("/persons/John")).hasForwardedUrl("persons/index");
|
||||
}
|
||||
|
||||
@Test
|
||||
void hasRedirectUrl() {
|
||||
assertThat(perform(post("/persons").param("name", "Andy"))).hasStatus(HttpStatus.FOUND)
|
||||
assertThat(mvc.post().uri("/persons").param("name", "Andy")).hasStatus(HttpStatus.FOUND)
|
||||
.hasRedirectedUrl("/persons/Andy");
|
||||
}
|
||||
|
||||
@Test
|
||||
void satisfiesAllowsAdditionalAssertions() {
|
||||
assertThat(this.mockMvc.perform(get("/greet"))).satisfies(result -> {
|
||||
assertThat(mvc.get().uri("/greet")).satisfies(result -> {
|
||||
assertThat(result).isInstanceOf(MvcTestResult.class);
|
||||
assertThat(result).hasStatusOk();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void resultMatcherCanBeReused() {
|
||||
assertThat(this.mockMvc.perform(get("/greet"))).matches(status().isOk());
|
||||
void resultMatcherCanBeReused() throws Exception {
|
||||
MvcTestResult result = mvc.get().uri("/greet").exchange();
|
||||
ResultMatcher matcher = mock(ResultMatcher.class);
|
||||
assertThat(result).matches(matcher);
|
||||
verify(matcher).match(result.getMvcResult());
|
||||
}
|
||||
|
||||
@Test
|
||||
void resultMatcherFailsWithDedicatedException() {
|
||||
ResultMatcher matcher = result -> assertThat(result.getResponse().getStatus())
|
||||
.isEqualTo(HttpStatus.NOT_FOUND.value());
|
||||
assertThatExceptionOfType(AssertionError.class)
|
||||
.isThrownBy(() -> assertThat(this.mockMvc.perform(get("/greet")))
|
||||
.matches(status().isNotFound()))
|
||||
.withMessageContaining("Status expected:<404> but was:<200>");
|
||||
.isThrownBy(() -> assertThat(mvc.get().uri("/greet"))
|
||||
.matches(matcher))
|
||||
.withMessageContaining("expected: 404").withMessageContaining(" but was: 200");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldApplyResultHandler() { // Spring RESTDocs example
|
||||
AtomicBoolean applied = new AtomicBoolean();
|
||||
assertThat(this.mockMvc.perform(get("/greet"))).apply(result -> applied.set(true));
|
||||
assertThat(mvc.get().uri("/greet")).apply(result -> applied.set(true));
|
||||
assertThat(applied).isTrue();
|
||||
}
|
||||
|
||||
|
||||
private MvcTestResult perform(MockHttpServletRequestBuilder builder) {
|
||||
return this.mockMvc.perform(builder);
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
@Import({ TestController.class, PersonController.class, AsyncController.class,
|
||||
|
|
|
|||
Loading…
Reference in New Issue