Skip to content

Commit c8967de

Browse files
committed
Provide better name for entry points
This commit renames AssertableMockMvc to MockMvcTester as the former was too mouthful, and we are looking for a naming pattern that can be applied consistently to test utilities that rely on AssertJ. Rather than AssertableMvcResult, we now use MvcTestResult and it no longer extends from MvcResult itself. That avoids having existing code that is migrated to the new API whilst assigning the result to MvcResult and get a bad DevXP as that doesn't bring any of the AssertJ support. See gh-32712
1 parent 5567d14 commit c8967de

File tree

7 files changed

+155
-192
lines changed

7 files changed

+155
-192
lines changed

spring-test/src/main/java/org/springframework/test/web/servlet/assertj/DefaultAssertableMvcResult.java spring-test/src/main/java/org/springframework/test/web/servlet/assertj/DefaultMvcTestResult.java

+18-61
Original file line numberDiff line numberDiff line change
@@ -21,107 +21,64 @@
2121
import org.springframework.mock.web.MockHttpServletRequest;
2222
import org.springframework.mock.web.MockHttpServletResponse;
2323
import org.springframework.test.web.servlet.MvcResult;
24-
import org.springframework.web.servlet.FlashMap;
25-
import org.springframework.web.servlet.HandlerInterceptor;
26-
import org.springframework.web.servlet.ModelAndView;
2724

2825
/**
29-
* The default {@link AssertableMvcResult} implementation.
26+
* The default {@link MvcTestResult} implementation.
3027
*
3128
* @author Stephane Nicoll
3229
* @since 6.2
3330
*/
34-
final class DefaultAssertableMvcResult implements AssertableMvcResult {
31+
final class DefaultMvcTestResult implements MvcTestResult {
3532

3633
@Nullable
37-
private final MvcResult target;
34+
private final MvcResult mvcResult;
3835

3936
@Nullable
4037
private final Exception unresolvedException;
4138

4239
@Nullable
4340
private final GenericHttpMessageConverter<Object> jsonMessageConverter;
4441

45-
DefaultAssertableMvcResult(@Nullable MvcResult target, @Nullable Exception unresolvedException, @Nullable GenericHttpMessageConverter<Object> jsonMessageConverter) {
46-
this.target = target;
42+
DefaultMvcTestResult(@Nullable MvcResult mvcResult, @Nullable Exception unresolvedException, @Nullable GenericHttpMessageConverter<Object> jsonMessageConverter) {
43+
this.mvcResult = mvcResult;
4744
this.unresolvedException = unresolvedException;
4845
this.jsonMessageConverter = jsonMessageConverter;
4946
}
5047

51-
/**
52-
* Return the exception that was thrown unexpectedly while processing the
53-
* request, if any.
54-
*/
48+
public MvcResult getMvcResult() {
49+
if (this.mvcResult == null) {
50+
throw new IllegalStateException(
51+
"Request has failed with unresolved exception " + this.unresolvedException);
52+
}
53+
return this.mvcResult;
54+
}
55+
5556
@Nullable
5657
public Exception getUnresolvedException() {
5758
return this.unresolvedException;
5859
}
5960

60-
@Override
6161
public MockHttpServletRequest getRequest() {
62-
return getTarget().getRequest();
62+
return getMvcResult().getRequest();
6363
}
6464

65-
@Override
6665
public MockHttpServletResponse getResponse() {
67-
return getTarget().getResponse();
68-
}
69-
70-
@Override
71-
@Nullable
72-
public Object getHandler() {
73-
return getTarget().getHandler();
74-
}
75-
76-
@Override
77-
@Nullable
78-
public HandlerInterceptor[] getInterceptors() {
79-
return getTarget().getInterceptors();
80-
}
81-
82-
@Override
83-
@Nullable
84-
public ModelAndView getModelAndView() {
85-
return getTarget().getModelAndView();
66+
return getMvcResult().getResponse();
8667
}
8768

88-
@Override
8969
@Nullable
9070
public Exception getResolvedException() {
91-
return getTarget().getResolvedException();
92-
}
93-
94-
@Override
95-
public FlashMap getFlashMap() {
96-
return getTarget().getFlashMap();
97-
}
98-
99-
@Override
100-
public Object getAsyncResult() {
101-
return getTarget().getAsyncResult();
71+
return getMvcResult().getResolvedException();
10272
}
10373

104-
@Override
105-
public Object getAsyncResult(long timeToWait) {
106-
return getTarget().getAsyncResult(timeToWait);
107-
}
108-
109-
110-
private MvcResult getTarget() {
111-
if (this.target == null) {
112-
throw new IllegalStateException(
113-
"Request has failed with unresolved exception " + this.unresolvedException);
114-
}
115-
return this.target;
116-
}
11774

11875
/**
11976
* Use AssertJ's {@link org.assertj.core.api.Assertions#assertThat assertThat}
12077
* instead.
12178
*/
12279
@Override
123-
public MvcResultAssert assertThat() {
124-
return new MvcResultAssert(this, this.jsonMessageConverter);
80+
public MvcTestResultAssert assertThat() {
81+
return new MvcTestResultAssert(this, this.jsonMessageConverter);
12582
}
12683

12784
}

spring-test/src/main/java/org/springframework/test/web/servlet/assertj/AssertableMockMvc.java spring-test/src/main/java/org/springframework/test/web/servlet/assertj/MockMvcTester.java

+60-29
Original file line numberDiff line numberDiff line change
@@ -38,23 +38,54 @@
3838
import org.springframework.web.context.WebApplicationContext;
3939

4040
/**
41-
* {@link MockMvc} variant that tests Spring MVC exchanges and provides fluent
42-
* assertions using {@link org.assertj.core.api.Assertions AssertJ}.
41+
* Test Spring MVC applications with {@link MockMvc} for server request handling
42+
* using {@link org.assertj.core.api.Assertions AssertJ}.
43+
*
44+
* <p>A tester instance can be created from a {@link WebApplicationContext}:
45+
* <pre><code class='java'>
46+
* // Create an instance with default settings
47+
* MockMvcTester mvc = MockMvcTester.from(applicationContext);
48+
*
49+
* // Create an instance with a custom Filter
50+
* MockMvcTester mvc = MockMvcTester.from(applicationContext,
51+
* builder -> builder.addFilters(filter).build());
52+
* </code></pre>
53+
*
54+
* <p>A tester can be created standalone by providing the controller(s) to
55+
* include in a standalone setup:<pre><code class='java'>
56+
* // Create an instance for PersonController
57+
* MockMvcTester mvc = MockMvcTester.of(new PersonController());
58+
* </code></pre>
59+
*
60+
* <p>Once a test instance is available, you can perform requests in
61+
* a similar fashion as with {@link MockMvc}, and wrapping the result in
62+
* {@code assertThat} provides access to assertions. For instance:
63+
* <pre><code class='java'>
64+
* // perform a GET on /hi and assert the response body is equal to Hello
65+
* assertThat(mvc.perform(get("/hi")))
66+
* .hasStatusOk().hasBodyTextEqualTo("Hello");
67+
* </code></pre>
4368
*
4469
* <p>A main difference with {@link MockMvc} is that an unresolved exception
45-
* is not thrown directly. Rather an {@link AssertableMvcResult} is available
46-
* with an {@link AssertableMvcResult#getUnresolvedException() unresolved
47-
* exception}.
70+
* is not thrown directly. Rather an {@link MvcTestResult} is available
71+
* with an {@link MvcTestResult#getUnresolvedException() unresolved
72+
* exception}. You can assert that a request has failed unexpectedly:
73+
* <pre><code class='java'>
74+
* // perform a GET on /hi and assert the response body is equal to Hello
75+
* assertThat(mvc.perform(get("/boom")))
76+
* .hasUnresolvedException())
77+
* .withMessage("Test exception");
78+
* </code></pre>
4879
*
49-
* <p>{@link AssertableMockMvc} can be configured with a list of
80+
* <p>{@link MockMvcTester} can be configured with a list of
5081
* {@linkplain HttpMessageConverter message converters} to allow the response
5182
* body to be deserialized, rather than asserting on the raw values.
5283
*
5384
* @author Stephane Nicoll
5485
* @author Brian Clozel
5586
* @since 6.2
5687
*/
57-
public final class AssertableMockMvc {
88+
public final class MockMvcTester {
5889

5990
private static final MediaType JSON = MediaType.APPLICATION_JSON;
6091

@@ -64,23 +95,23 @@ public final class AssertableMockMvc {
6495
private final GenericHttpMessageConverter<Object> jsonMessageConverter;
6596

6697

67-
private AssertableMockMvc(MockMvc mockMvc, @Nullable GenericHttpMessageConverter<Object> jsonMessageConverter) {
98+
private MockMvcTester(MockMvc mockMvc, @Nullable GenericHttpMessageConverter<Object> jsonMessageConverter) {
6899
Assert.notNull(mockMvc, "mockMVC should not be null");
69100
this.mockMvc = mockMvc;
70101
this.jsonMessageConverter = jsonMessageConverter;
71102
}
72103

73104
/**
74-
* Create a {@link AssertableMockMvc} instance that delegates to the given
105+
* Create a {@link MockMvcTester} instance that delegates to the given
75106
* {@link MockMvc} instance.
76107
* @param mockMvc the MockMvc instance to delegate calls to
77108
*/
78-
public static AssertableMockMvc create(MockMvc mockMvc) {
79-
return new AssertableMockMvc(mockMvc, null);
109+
public static MockMvcTester create(MockMvc mockMvc) {
110+
return new MockMvcTester(mockMvc, null);
80111
}
81112

82113
/**
83-
* Create an {@link AssertableMockMvc} instance using the given, fully
114+
* Create an {@link MockMvcTester} instance using the given, fully
84115
* initialized (i.e., <em>refreshed</em>) {@link WebApplicationContext}. The
85116
* given {@code customizations} are applied to the {@link DefaultMockMvcBuilder}
86117
* that ultimately creates the underlying {@link MockMvc} instance.
@@ -92,7 +123,7 @@ public static AssertableMockMvc create(MockMvc mockMvc) {
92123
* instance based on a {@link DefaultMockMvcBuilder}.
93124
* @see MockMvcBuilders#webAppContextSetup(WebApplicationContext)
94125
*/
95-
public static AssertableMockMvc from(WebApplicationContext applicationContext,
126+
public static MockMvcTester from(WebApplicationContext applicationContext,
96127
Function<DefaultMockMvcBuilder, MockMvc> customizations) {
97128

98129
DefaultMockMvcBuilder builder = MockMvcBuilders.webAppContextSetup(applicationContext);
@@ -101,7 +132,7 @@ public static AssertableMockMvc from(WebApplicationContext applicationContext,
101132
}
102133

103134
/**
104-
* Shortcut to create an {@link AssertableMockMvc} instance using the given,
135+
* Shortcut to create an {@link MockMvcTester} instance using the given,
105136
* fully initialized (i.e., <em>refreshed</em>) {@link WebApplicationContext}.
106137
* <p>Consider using {@link #from(WebApplicationContext, Function)} if
107138
* further customization of the underlying {@link MockMvc} instance is
@@ -110,12 +141,12 @@ public static AssertableMockMvc from(WebApplicationContext applicationContext,
110141
* MVC infrastructure and application controllers from
111142
* @see MockMvcBuilders#webAppContextSetup(WebApplicationContext)
112143
*/
113-
public static AssertableMockMvc from(WebApplicationContext applicationContext) {
144+
public static MockMvcTester from(WebApplicationContext applicationContext) {
114145
return from(applicationContext, DefaultMockMvcBuilder::build);
115146
}
116147

117148
/**
118-
* Create an {@link AssertableMockMvc} instance by registering one or more
149+
* Create an {@link MockMvcTester} instance by registering one or more
119150
* {@code @Controller} instances and configuring Spring MVC infrastructure
120151
* programmatically.
121152
* <p>This allows full control over the instantiation and initialization of
@@ -129,16 +160,16 @@ public static AssertableMockMvc from(WebApplicationContext applicationContext) {
129160
* Spring MVC infrastructure
130161
* @see MockMvcBuilders#standaloneSetup(Object...)
131162
*/
132-
public static AssertableMockMvc of(Collection<?> controllers,
163+
public static MockMvcTester of(Collection<?> controllers,
133164
Function<StandaloneMockMvcBuilder, MockMvc> customizations) {
134165

135166
StandaloneMockMvcBuilder builder = MockMvcBuilders.standaloneSetup(controllers.toArray());
136167
return create(customizations.apply(builder));
137168
}
138169

139170
/**
140-
* Shortcut to create an {@link AssertableMockMvc} instance by registering
141-
* one or more {@code @Controller} instances.
171+
* Shortcut to create an {@link MockMvcTester} instance by registering one
172+
* or more {@code @Controller} instances.
142173
* <p>The minimum infrastructure required by the
143174
* {@link org.springframework.web.servlet.DispatcherServlet DispatcherServlet}
144175
* to serve requests with annotated controllers is created. Consider using
@@ -149,26 +180,26 @@ public static AssertableMockMvc of(Collection<?> controllers,
149180
* into an instance
150181
* @see MockMvcBuilders#standaloneSetup(Object...)
151182
*/
152-
public static AssertableMockMvc of(Object... controllers) {
183+
public static MockMvcTester of(Object... controllers) {
153184
return of(Arrays.asList(controllers), StandaloneMockMvcBuilder::build);
154185
}
155186

156187
/**
157-
* Return a new {@link AssertableMockMvc} instance using the specified
188+
* Return a new {@link MockMvcTester} instance using the specified
158189
* {@linkplain HttpMessageConverter message converters}.
159190
* <p>If none are specified, only basic assertions on the response body can
160191
* be performed. Consider registering a suitable JSON converter for asserting
161192
* against JSON data structures.
162193
* @param httpMessageConverters the message converters to use
163194
* @return a new instance using the specified converters
164195
*/
165-
public AssertableMockMvc withHttpMessageConverters(Iterable<HttpMessageConverter<?>> httpMessageConverters) {
166-
return new AssertableMockMvc(this.mockMvc, findJsonMessageConverter(httpMessageConverters));
196+
public MockMvcTester withHttpMessageConverters(Iterable<HttpMessageConverter<?>> httpMessageConverters) {
197+
return new MockMvcTester(this.mockMvc, findJsonMessageConverter(httpMessageConverters));
167198
}
168199

169200
/**
170-
* Perform a request and return a type that can be used with standard
171-
* {@link org.assertj.core.api.Assertions AssertJ} assertions.
201+
* Perform a request and return a {@link MvcTestResult result} that can be
202+
* used with standard {@link org.assertj.core.api.Assertions AssertJ} assertions.
172203
* <p>Use static methods of {@link MockMvcRequestBuilders} to prepare the
173204
* request, wrapping the invocation in {@code assertThat}. The following
174205
* asserts that a {@linkplain MockMvcRequestBuilders#get(URI) GET} request
@@ -191,16 +222,16 @@ public AssertableMockMvc withHttpMessageConverters(Iterable<HttpMessageConverter
191222
* @param requestBuilder used to prepare the request to execute;
192223
* see static factory methods in
193224
* {@link org.springframework.test.web.servlet.request.MockMvcRequestBuilders}
194-
* @return an {@link AssertableMvcResult} to be wrapped in {@code assertThat}
225+
* @return an {@link MvcTestResult} to be wrapped in {@code assertThat}
195226
* @see MockMvc#perform(RequestBuilder)
196227
*/
197-
public AssertableMvcResult perform(RequestBuilder requestBuilder) {
228+
public MvcTestResult perform(RequestBuilder requestBuilder) {
198229
Object result = getMvcResultOrFailure(requestBuilder);
199230
if (result instanceof MvcResult mvcResult) {
200-
return new DefaultAssertableMvcResult(mvcResult, null, this.jsonMessageConverter);
231+
return new DefaultMvcTestResult(mvcResult, null, this.jsonMessageConverter);
201232
}
202233
else {
203-
return new DefaultAssertableMvcResult(null, (Exception) result, this.jsonMessageConverter);
234+
return new DefaultMvcTestResult(null, (Exception) result, this.jsonMessageConverter);
204235
}
205236
}
206237

spring-test/src/main/java/org/springframework/test/web/servlet/assertj/AssertableMvcResult.java spring-test/src/main/java/org/springframework/test/web/servlet/assertj/MvcTestResult.java

+18-7
Original file line numberDiff line numberDiff line change
@@ -22,23 +22,34 @@
2222
import org.springframework.test.web.servlet.MvcResult;
2323

2424
/**
25-
* A {@link MvcResult} that additionally supports AssertJ style assertions.
25+
* Provide to the result of an executed request using {@link MockMvcTester} that
26+
* is meant to be used with {@link org.assertj.core.api.Assertions#assertThat(AssertProvider)
27+
* assertThat}.
2628
*
2729
* <p>Can be in one of two distinct states:
2830
* <ol>
29-
* <li>The request processed successfully, and {@link #getUnresolvedException()}
30-
* is therefore {@code null}.</li>
31+
* <li>The request processed successfully, even if it fails with an exception
32+
* that has been resolved. {@link #getMvcResult()} is available and
33+
* {@link #getUnresolvedException()} is {@code null}.</li>
3134
* <li>The request failed unexpectedly with {@link #getUnresolvedException()}
32-
* providing more information about the error. Any attempt to access a member of
33-
* the result fails with an exception.</li>
35+
* providing more information about the error. Any attempt to access
36+
* {@link #getMvcResult() the result } fails with an exception.</li>
3437
* </ol>
3538
*
3639
* @author Stephane Nicoll
3740
* @author Brian Clozel
3841
* @since 6.2
39-
* @see AssertableMockMvc
42+
* @see MockMvcTester
4043
*/
41-
public interface AssertableMvcResult extends MvcResult, AssertProvider<MvcResultAssert> {
44+
public interface MvcTestResult extends AssertProvider<MvcTestResultAssert> {
45+
46+
/**
47+
* Return the {@link MvcResult result} of the processing.
48+
* <p>If the request has failed unexpectedly, this throws an
49+
* {@link IllegalStateException}.
50+
* @return the {@link MvcResult}
51+
*/
52+
MvcResult getMvcResult();
4253

4354
/**
4455
* Return the exception that was thrown unexpectedly while processing the

0 commit comments

Comments
 (0)