Document AssertJ support for MockMvc
This commit restructures the section on MockMvc so that the anchors are easier to read. The standard integration has moved to a Hamcrest Integration section at the same level as HtmlUnit Integration, and a new AssertJ Integration section has been created. Closes gh-32454
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
[[mockmvc-tester-assertions]]
|
||||
= Defining Expectations
|
||||
|
||||
Assertions work the same way as any AssertJ assertions. The support provides dedicated
|
||||
assert objects for the various pieces of the `MvcTestResult`, as shown in the following
|
||||
example:
|
||||
|
||||
include-code::./HotelControllerTests[tag=get,indent=0]
|
||||
|
||||
If a request fails, the exchange does not throw the exception. Rather, you can assert
|
||||
that the result of the exchange has failed:
|
||||
|
||||
include-code::./HotelControllerTests[tag=failure,indent=0]
|
||||
|
||||
The request could also fail unexpectedly, that is the exception thrown by the handler
|
||||
has not been handled and is thrown as is. You can still use `.hasFailed()` and
|
||||
`.failure()` but any attempt to access part of the result will throw an exception as
|
||||
the exchange hasn't completed.
|
||||
|
||||
[[mockmvc-tester-assertions-json]]
|
||||
== JSON Support
|
||||
|
||||
The AssertJ support for `MvcTestResult` provides JSON support via `bodyJson()`.
|
||||
|
||||
If https://github.com/jayway/JsonPath[JSONPath] is available, you can apply an expression
|
||||
on the JSON document. The returned value provides convenient methods to return a dedicated
|
||||
assert object for the various supported JSON data types:
|
||||
|
||||
include-code::./FamilyControllerTests[tag=extract-asmap,indent=0]
|
||||
|
||||
You can also convert the raw content to any of your data types as long as the message
|
||||
converter is configured properly:
|
||||
|
||||
include-code::./FamilyControllerTests[tag=extract-convert,indent=0]
|
||||
|
||||
Converting to a target `Class` provides a generic assert object. For more complex types,
|
||||
you may want to use `AssertFactory` instead that returns a dedicated assert type, if
|
||||
possible:
|
||||
|
||||
include-code::./FamilyControllerTests[tag=extract-convert-assert-factory,indent=0]
|
||||
|
||||
https://jsonassert.skyscreamer.org[JSONAssert] is also supported. The body of the
|
||||
response can be matched against a `Resource` or a content. If the content ends with
|
||||
`.json ` we look for a file matching that name on the classpath:
|
||||
|
||||
include-code::./FamilyControllerTests[tag=assert-file,indent=0]
|
||||
|
||||
If you prefer to use another library, you can provide an implementation of
|
||||
{spring-framework-api}/test/json/JsonComparator.html[`JsonComparator`].
|
||||
@@ -0,0 +1,23 @@
|
||||
[[mockmvc-tester-integration]]
|
||||
= MockMvc integration
|
||||
|
||||
If you want to use the AssertJ support but have invested in the original `MockMvc`
|
||||
API, `MockMvcTester` offers several ways to integrate with it.
|
||||
|
||||
If you have your own `RequestBuilder` implementation, you can trigger the processing
|
||||
of the request using `perform`. The example below showcases how the query can be
|
||||
crafted with the original API:
|
||||
|
||||
include-code::./HotelControllerTests[tag=perform,indent=0]
|
||||
|
||||
Similarly, if you have crafted custom matchers that you use with the `.andExpect` feature
|
||||
of `MockMvc` you can use them via `.matches`. In the example below, we rewrite the
|
||||
preceding example to assert the status with the `ResultMatcher` implementation that
|
||||
`MockMvc` provides:
|
||||
|
||||
include-code::./HotelControllerTests[tag=matches,indent=0]
|
||||
|
||||
`MockMvc` also defines a `ResultHandler` contract that lets you execute arbitrary actions
|
||||
on `MvcResult`. If you have implemented this contract you can invoke it using `.apply`.
|
||||
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
[[mockmvc-tester-requests]]
|
||||
= Performing Requests
|
||||
|
||||
This section shows how to use `MockMvcTester` to perform requests and its integration
|
||||
with AssertJ to verify responses.
|
||||
|
||||
`MockMvcTester` provides a fluent API to compose the request that reuses the same
|
||||
`MockHttpServletRequestBuilder` as the Hamcrest support, except that there is no need
|
||||
to import a static method. The builder that is returned is AssertJ-aware so that
|
||||
wrapping it in the regular `assertThat()` factory method triggers the exchange and
|
||||
provides access to a dedicated Assert object for `MvcTestResult`.
|
||||
|
||||
Here is a simple example that performs a `POST` on `/hotels/42` and configures the
|
||||
request to specify an `Accept` header:
|
||||
|
||||
include-code::./HotelControllerTests[tag=post,indent=0]
|
||||
|
||||
AssertJ often consists of multiple `assertThat()` statements to validate the different
|
||||
parts of the exchange. Rather than having a single statement as in the case above, you
|
||||
can use `.exchange()` to return a `MvcTestResult` that can be used in multiple
|
||||
`assertThat` statements:
|
||||
|
||||
include-code::./HotelControllerTests[tag=post-exchange,indent=0]
|
||||
|
||||
You can specify query parameters in URI template style, as the following example shows:
|
||||
|
||||
include-code::./HotelControllerTests[tag=query-parameters,indent=0]
|
||||
|
||||
You can also add Servlet request parameters that represent either query or form
|
||||
parameters, as the following example shows:
|
||||
|
||||
include-code::./HotelControllerTests[tag=parameters,indent=0]
|
||||
|
||||
If application code relies on Servlet request parameters and does not check the query
|
||||
string explicitly (as is most often the case), it does not matter which option you use.
|
||||
Keep in mind, however, that query parameters provided with the URI template are decoded
|
||||
while request parameters provided through the `param(...)` method are expected to already
|
||||
be decoded.
|
||||
|
||||
|
||||
[[mockmvc-tester-requests-async]]
|
||||
== Async
|
||||
|
||||
If the processing of the request is done asynchronously, `exchange()` waits for
|
||||
the completion of the request so that the result to assert is effectively immutable.
|
||||
The default timeout is 10 seconds but it can be controlled on a request-by-request
|
||||
basis as shown in the following example:
|
||||
|
||||
include-code::./AsyncControllerTests[tag=duration,indent=0]
|
||||
|
||||
If you prefer to get the raw result and manage the lifecycle of the asynchronous
|
||||
request yourself, use `asyncExchange` rather than `exchange`.
|
||||
|
||||
[[mockmvc-tester-requests-multipart]]
|
||||
== Multipart
|
||||
|
||||
You can perform file upload requests that internally use
|
||||
`MockMultipartHttpServletRequest` so that there is no actual parsing of a multipart
|
||||
request. Rather, you have to set it up to be similar to the following example:
|
||||
|
||||
include-code::./MultipartControllerTests[tag=snippet,indent=0]
|
||||
|
||||
[[mockmvc-tester-requests-paths]]
|
||||
== Using Servlet and Context Paths
|
||||
|
||||
In most cases, it is preferable to leave the context path and the Servlet path out of the
|
||||
request URI. If you must test with the full request URI, be sure to set the `contextPath`
|
||||
and `servletPath` accordingly so that request mappings work, as the following example
|
||||
shows:
|
||||
|
||||
include-code::./HotelControllerTests[tag=context-servlet-paths,indent=0]
|
||||
|
||||
In the preceding example, it would be cumbersome to set the `contextPath` and
|
||||
`servletPath` with every performed request. Instead, you can set up default request
|
||||
properties, as the following example shows:
|
||||
|
||||
include-code::./HotelControllerTests[tag=default-customizations,indent=0]
|
||||
|
||||
The preceding properties affect every request performed through the `mockMvc` instance.
|
||||
If the same property is also specified on a given request, it overrides the default
|
||||
value. That is why the HTTP method and URI in the default request do not matter, since
|
||||
they must be specified on every request.
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
[[mockmvc-tester-setup]]
|
||||
= Configuring MockMvcTester
|
||||
|
||||
`MockMvcTester` can be setup in one of two ways. One is to point directly to the
|
||||
controllers you want to test and programmatically configure Spring MVC infrastructure.
|
||||
The second is to point to Spring configuration with Spring MVC and controller
|
||||
infrastructure in it.
|
||||
|
||||
TIP: For a comparison of those two modes, check xref:testing/mockmvc/setup-options.adoc[Setup Options].
|
||||
|
||||
To set up `MockMvcTester` for testing a specific controller, use the following:
|
||||
|
||||
include-code::./AccountControllerStandaloneTests[tag=snippet,indent=0]
|
||||
|
||||
To set up `MockMvcTester` through Spring configuration, use the following:
|
||||
|
||||
include-code::./AccountControllerIntegrationTests[tag=snippet,indent=0]
|
||||
|
||||
`MockMvcTester` can convert the JSON response body, or the result of a JSONPath expression,
|
||||
to one of your domain object as long as the relevant `HttpMessageConverter` is registered.
|
||||
|
||||
If you use Jackson to serialize content to JSON, the following example registers the
|
||||
converter:
|
||||
|
||||
include-code::./converter/AccountControllerIntegrationTests[tag=snippet,indent=0]
|
||||
|
||||
NOTE: The above assumes the converter has been registered as a Bean.
|
||||
|
||||
Finally, if you have a `MockMvc` instance handy, you can create a `MockMvcTester` by
|
||||
providing the `MockMvc` instance to use using the `create` factory method.
|
||||
Reference in New Issue
Block a user