Polish Spring MVC Test content
This commit is contained in:
parent
fefc4b478f
commit
9bb29fbc34
|
@ -3685,67 +3685,39 @@ instrumenting your test class with a `TestContextManager`. See the source code o
|
||||||
[[spring-mvc-test-framework]]
|
[[spring-mvc-test-framework]]
|
||||||
=== Spring MVC Test Framework
|
=== Spring MVC Test Framework
|
||||||
|
|
||||||
.Standalone project
|
The __Spring MVC Test framework__ provides first class JUnit support for testing
|
||||||
****
|
Spring MVC code using a fluent API. It's built on the
|
||||||
Before inclusion in Spring Framework 3.2, the Spring MVC Test framework had already
|
http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/mock/web/package-summary.html[Servlet API mock objects]
|
||||||
existed as a separate project on GitHub where it grew and evolved through actual use,
|
from the `spring-test` module and hence does not require a running Servlet container,
|
||||||
feedback, and the contribution of many.
|
it uses the `DispatcherServlet` thus providing full Spring MVC support, and
|
||||||
|
may optionally load actual Spring configuration with the __TestContext framework__
|
||||||
|
in addition to a standalone mode in which controllers may be instantiated manually
|
||||||
|
and tested one at a time.
|
||||||
|
|
||||||
The standalone https://github.com/spring-projects/spring-test-mvc[spring-test-mvc project]
|
__Spring MVC Test__ also provides client-side support for testing code that uses
|
||||||
is still available on GitHub and can be used in conjunction with Spring Framework 3.1.x.
|
the `RestTemplate`. Client-side tests mock the server responses and also do not
|
||||||
Applications upgrading to 3.2 or later should replace the `spring-test-mvc` dependency with a
|
require a running server.
|
||||||
dependency on `spring-test`.
|
|
||||||
|
|
||||||
The `spring-test` module uses a different package `org.springframework.test.web` but
|
|
||||||
otherwise is nearly identical with two exceptions. One is support for features new in
|
|
||||||
3.2 (e.g. asynchronous web requests). The other relates to the options for creating a
|
|
||||||
`MockMvc` instance. In Spring Framework 3.2 and later, this can only be done through the
|
|
||||||
TestContext framework, which provides caching benefits for the loaded configuration.
|
|
||||||
****
|
|
||||||
|
|
||||||
The __Spring MVC Test framework__ provides first class JUnit support for testing client
|
|
||||||
and server-side Spring MVC code through a fluent API. Typically it loads the actual
|
|
||||||
Spring configuration through the __TestContext framework__ and always uses the
|
|
||||||
`DispatcherServlet` to process requests thus approximating full integration tests
|
|
||||||
without requiring a running Servlet container.
|
|
||||||
|
|
||||||
Client-side tests are `RestTemplate`-based and allow tests for code that relies on the
|
|
||||||
`RestTemplate` without requiring a running server to respond to the requests.
|
|
||||||
|
|
||||||
|
|
||||||
[[spring-mvc-test-server]]
|
[[spring-mvc-test-server]]
|
||||||
==== Server-Side Tests
|
==== Server-Side Tests
|
||||||
Before Spring Framework 3.2, the most likely way to test a Spring MVC controller was to
|
It's easy to write a plain JUnit test for a Spring MVC controller. Simply instantiate
|
||||||
write a unit test that instantiates the controller, injects it with mock or stub
|
the controller, inject it with mock or stub dependencies, and call its methods
|
||||||
dependencies, and then calls its methods directly, using a `MockHttpServletRequest` and
|
passing `MockHttpServletRequest`, `MockHttpServletResponse`, etc. if necessary.
|
||||||
`MockHttpServletResponse` where necessary.
|
However much remains untested, e.g. request mappings, data binding, type conversion,
|
||||||
|
validation and much more. Furthermore other controller methods such as `@InitBinder`,
|
||||||
|
`@ModelAttribute`, and `@ExceptionHandler` may also be invoked as part of the request
|
||||||
|
processing lifecycle.
|
||||||
|
|
||||||
Although this is pretty easy to do, controllers have many annotations, and much remains
|
The goal of __Spring MVC Test__ is to provide an effective way of testing controllers
|
||||||
untested. Request mappings, data binding, type conversion, and validation are just a few
|
by performing requests and generating responses through the `DispatcherServlet`.
|
||||||
examples of what isn't tested. Furthermore, there are other types of annotated methods
|
|
||||||
such as `@InitBinder`, `@ModelAttribute`, and `@ExceptionHandler` that get invoked as
|
|
||||||
part of request processing.
|
|
||||||
|
|
||||||
The idea behind Spring MVC Test is to be able to re-write those controller tests by
|
__Spring MVC Test__ builds on the familiar "mock" implementations of the Servlet API
|
||||||
performing actual requests and generating responses, as they would be at runtime, along
|
|
||||||
the way invoking controllers through the Spring MVC `DispatcherServlet`. Controllers can
|
|
||||||
still be injected with mock dependencies, so tests can remain focused on the web layer.
|
|
||||||
|
|
||||||
Spring MVC Test builds on the familiar "mock" implementations of the Servlet API
|
|
||||||
available in the `spring-test` module. This allows performing requests and generating
|
available in the `spring-test` module. This allows performing requests and generating
|
||||||
responses without the need for running in a Servlet container. For the most part
|
responses without the need for running in a Servlet container. For the most part
|
||||||
everything should work as it does at runtime with the exception of JSP rendering, which
|
everything should work as it does at runtime with a few notable exceptions as
|
||||||
is not available outside a Servlet container. Furthermore, if you are familiar with how
|
explained further below. Here is an example of using Spring MVC Test:
|
||||||
the `MockHttpServletResponse` works, you'll know that forwards and redirects are not
|
|
||||||
actually executed. Instead "forwarded" and "redirected" URLs are saved and can be
|
|
||||||
asserted in tests. This means if you are using JSPs, you can verify the JSP page to
|
|
||||||
which the request was forwarded.
|
|
||||||
|
|
||||||
All other means of rendering including `@ResponseBody` methods and `View` types (besides
|
|
||||||
JSPs) such as Freemarker, Velocity, Thymeleaf, and others for rendering HTML, JSON, XML,
|
|
||||||
and so on should work as expected, and the response will contain the generated content.
|
|
||||||
|
|
||||||
Below is an example of a test requesting account information in JSON format:
|
|
||||||
|
|
||||||
[source,java,indent=0]
|
[source,java,indent=0]
|
||||||
----
|
----
|
||||||
|
@ -3778,17 +3750,17 @@ Below is an example of a test requesting account information in JSON format:
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
The test relies on the `WebApplicationContext` support of the __TestContext framework__.
|
The above test relies on the `WebApplicationContext` support of the __TestContext framework__
|
||||||
It loads Spring configuration from an XML configuration file located in the same package
|
to loads Spring configuration from an XML configuration file located in the same package
|
||||||
as the test class (also supports JavaConfig) and injects the created
|
as the test class but also supported is Java-based configuration. See these
|
||||||
`WebApplicationContext` into the test so a `MockMvc` instance can be created with it.
|
https://github.com/spring-projects/spring-framework/tree/master/spring-test/src/test/java/org/springframework/test/web/servlet/samples/context[sample tests].
|
||||||
|
|
||||||
The `MockMvc` is then used to perform a request to `"/accounts/1"` and verify the
|
The `MockMvc` instance is used to perform a request to `"/accounts/1"` and verify the
|
||||||
resulting response status is 200, the response content type is `"application/json"`, and
|
resulting response has status 200, content type is `"application/json"`, and
|
||||||
response content has a JSON property called "name" with the value "Lee". JSON content is
|
response body has a JSON property called "name" with the value "Lee". The jsonPath
|
||||||
inspected with the help of Jayway's https://github.com/jayway/JsonPath[JsonPath
|
syntax is supported through the Jayway https://github.com/jayway/JsonPath[JsonPath
|
||||||
project]. There are lots of other options for verifying the result of the performed
|
project]. There are lots of other options for verifying the result of the performed
|
||||||
request and those will be discussed later.
|
request that will be discussed below.
|
||||||
|
|
||||||
[[spring-mvc-test-server-static-imports]]
|
[[spring-mvc-test-server-static-imports]]
|
||||||
===== Static Imports
|
===== Static Imports
|
||||||
|
@ -3804,10 +3776,8 @@ completion on static members.
|
||||||
|
|
||||||
[[spring-mvc-test-server-setup-options]]
|
[[spring-mvc-test-server-setup-options]]
|
||||||
===== Setup Options
|
===== Setup Options
|
||||||
The goal of server-side test setup is to create an instance of `MockMvc` that can be
|
There are two main options for creating an instance of `MockMvc`.
|
||||||
used to perform requests. There are two main options.
|
The first is to load Spring MVC configuration through the __TestContext
|
||||||
|
|
||||||
The first option is to point to Spring MVC configuration through the __TestContext
|
|
||||||
framework__, which loads the Spring configuration and injects a `WebApplicationContext`
|
framework__, which loads the Spring configuration and injects a `WebApplicationContext`
|
||||||
into the test to use to create a `MockMvc`:
|
into the test to use to create a `MockMvc`:
|
||||||
|
|
||||||
|
@ -3834,11 +3804,10 @@ into the test to use to create a `MockMvc`:
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
The second option is to simply register a controller instance without loading any Spring
|
The second is to simply create a controller instance manually without loading Spring
|
||||||
configuration. Instead basic Spring MVC configuration suitable for testing annotated
|
configuration. Instead basic default configuration, roughly comparable to that of
|
||||||
controllers is automatically created. The created configuration is comparable to that of
|
the MVC JavaConfig or the MVC namespace, is automatically created and can be customized
|
||||||
the MVC JavaConfig (and the MVC namespace) and can be customized to a degree through
|
to a degree:
|
||||||
builder-style methods:
|
|
||||||
|
|
||||||
[source,java,indent=0]
|
[source,java,indent=0]
|
||||||
[subs="verbatim,quotes"]
|
[subs="verbatim,quotes"]
|
||||||
|
@ -3857,7 +3826,7 @@ builder-style methods:
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
Which option should you use?
|
Which setup option should you use?
|
||||||
|
|
||||||
The __"webAppContextSetup"__ loads the actual Spring MVC configuration resulting in a
|
The __"webAppContextSetup"__ loads the actual Spring MVC configuration resulting in a
|
||||||
more complete integration test. Since the __TestContext framework__ caches the loaded
|
more complete integration test. Since the __TestContext framework__ caches the loaded
|
||||||
|
@ -3913,8 +3882,7 @@ verify the Spring MVC configuration. Alternatively, you can decide to write all
|
||||||
|
|
||||||
[[spring-mvc-test-server-performing-requests]]
|
[[spring-mvc-test-server-performing-requests]]
|
||||||
===== Performing Requests
|
===== Performing Requests
|
||||||
To perform requests, use the appropriate HTTP method and additional builder-style
|
It's easy to perform requests using any HTTP method:
|
||||||
methods corresponding to properties of `MockHttpServletRequest`. For example:
|
|
||||||
|
|
||||||
[source,java,indent=0]
|
[source,java,indent=0]
|
||||||
[subs="verbatim,quotes"]
|
[subs="verbatim,quotes"]
|
||||||
|
@ -3922,8 +3890,9 @@ methods corresponding to properties of `MockHttpServletRequest`. For example:
|
||||||
mockMvc.perform(post("/hotels/{id}", 42).accept(MediaType.APPLICATION_JSON));
|
mockMvc.perform(post("/hotels/{id}", 42).accept(MediaType.APPLICATION_JSON));
|
||||||
----
|
----
|
||||||
|
|
||||||
In addition to all the HTTP methods, you can also perform file upload requests, which
|
You can also perform file upload requests that internally use
|
||||||
internally creates an instance of `MockMultipartHttpServletRequest`:
|
`MockMultipartHttpServletRequest` so that there is no actual parsing of a multipart
|
||||||
|
request but rather you have to set it up:
|
||||||
|
|
||||||
[source,java,indent=0]
|
[source,java,indent=0]
|
||||||
[subs="verbatim,quotes"]
|
[subs="verbatim,quotes"]
|
||||||
|
@ -3931,7 +3900,7 @@ internally creates an instance of `MockMultipartHttpServletRequest`:
|
||||||
mockMvc.perform(fileUpload("/doc").file("a1", "ABC".getBytes("UTF-8")));
|
mockMvc.perform(fileUpload("/doc").file("a1", "ABC".getBytes("UTF-8")));
|
||||||
----
|
----
|
||||||
|
|
||||||
Query string parameters can be specified in the URI template:
|
You can specify query parameters in URI template style:
|
||||||
|
|
||||||
[source,java,indent=0]
|
[source,java,indent=0]
|
||||||
[subs="verbatim,quotes"]
|
[subs="verbatim,quotes"]
|
||||||
|
@ -3939,7 +3908,7 @@ Query string parameters can be specified in the URI template:
|
||||||
mockMvc.perform(get("/hotels?foo={foo}", "bar"));
|
mockMvc.perform(get("/hotels?foo={foo}", "bar"));
|
||||||
----
|
----
|
||||||
|
|
||||||
Or by adding Servlet request parameters:
|
Or you can add Servlet request parameters representing either query of form parameters:
|
||||||
|
|
||||||
[source,java,indent=0]
|
[source,java,indent=0]
|
||||||
[subs="verbatim,quotes"]
|
[subs="verbatim,quotes"]
|
||||||
|
@ -3947,10 +3916,10 @@ Or by adding Servlet request parameters:
|
||||||
mockMvc.perform(get("/hotels").param("foo", "bar"));
|
mockMvc.perform(get("/hotels").param("foo", "bar"));
|
||||||
----
|
----
|
||||||
|
|
||||||
If application code relies on Servlet request parameters, and doesn't check the query
|
If application code relies on Servlet request parameters and doesn't check the query
|
||||||
string, as is most often the case, then it doesn't matter how parameters are added. Keep
|
string explicitly (as is most often the case) then it doesn't matter which option you use.
|
||||||
in mind though that parameters provided in the URI template will be decoded while
|
Keep in mind however that query params provided with the URI template will be decoded while
|
||||||
parameters provided through the `param(...)` method are expected to be decoded.
|
request parameters provided through the `param(...)` method are expected to be decoded.
|
||||||
|
|
||||||
In most cases it's preferable to leave out the context path and the Servlet path from
|
In most cases it's preferable to leave out the context path and the Servlet path from
|
||||||
the request URI. If you must test with the full request URI, be sure to set the
|
the request URI. If you must test with the full request URI, be sure to set the
|
||||||
|
@ -3963,8 +3932,8 @@ the request URI. If you must test with the full request URI, be sure to set the
|
||||||
----
|
----
|
||||||
|
|
||||||
Looking at the above example, it would be cumbersome to set the contextPath and
|
Looking at the above example, it would be cumbersome to set the contextPath and
|
||||||
servletPath with every performed request. That's why you can define default request
|
servletPath with every performed request. Instead you can set up default request
|
||||||
properties when building the `MockMvc`:
|
properties:
|
||||||
|
|
||||||
[source,java,indent=0]
|
[source,java,indent=0]
|
||||||
[subs="verbatim,quotes"]
|
[subs="verbatim,quotes"]
|
||||||
|
@ -3982,15 +3951,15 @@ properties when building the `MockMvc`:
|
||||||
}
|
}
|
||||||
----
|
----
|
||||||
|
|
||||||
The above properties will apply to every request performed through the `MockMvc`. If the
|
The above properties will affect every request performed through the `MockMvc` instance.
|
||||||
same property is also specified on a given request, it will override the default value.
|
If the same property is also specified on a given request, it overrides the default value.
|
||||||
That is why, the HTTP method and URI don't matter, when setting default request
|
That is why the HTTP method and URI in default request don't matter since they must be
|
||||||
properties, since they must be specified on every request.
|
specified on every request.
|
||||||
|
|
||||||
[[spring-mvc-test-server-defining-expectations]]
|
[[spring-mvc-test-server-defining-expectations]]
|
||||||
===== Defining Expectations
|
===== Defining Expectations
|
||||||
Expectations can be defined by appending one or more `.andExpect(..)` after call to
|
Expectations can be defined by appending one or more `.andExpect(..)` calls after
|
||||||
perform the request:
|
performing a request:
|
||||||
|
|
||||||
[source,java,indent=0]
|
[source,java,indent=0]
|
||||||
[subs="verbatim,quotes"]
|
[subs="verbatim,quotes"]
|
||||||
|
@ -3998,18 +3967,18 @@ perform the request:
|
||||||
mockMvc.perform(get("/accounts/1")).andExpect(status().isOk());
|
mockMvc.perform(get("/accounts/1")).andExpect(status().isOk());
|
||||||
----
|
----
|
||||||
|
|
||||||
`MockMvcResultMatchers.*` defines a number of static members, some of which return types
|
`MockMvcResultMatchers.*` provides a number of expectations some of which are further
|
||||||
with additional methods, for asserting the result of the performed request. The
|
nested with more detailed expectations.
|
||||||
assertions fall in two general categories.
|
|
||||||
|
|
||||||
The first category of assertions verify properties of the response, i.e the response
|
Expectations fall in two general categories. The first category of assertions verify
|
||||||
status, headers, and content. Those are the most important things to test for.
|
properties of the response, i.e the response status, headers, and content. Those
|
||||||
|
are the most important results to assert.
|
||||||
|
|
||||||
The second category of assertions go beyond the response, and allow inspecting Spring
|
The second category of assertions go beyond the response. They allow inspecting Spring
|
||||||
MVC specific constructs such as which controller method processed the request, whether
|
MVC specific things such as which controller method processed the request, whether
|
||||||
an exception was raised and handled, what the content of the model is, what view was
|
an exception was raised and handled, what the content of the model is, what view was
|
||||||
selected, what flash attributes were added, and so on. It is also possible to verify
|
selected, what flash attributes were added, and so on. They also allow inspecting
|
||||||
Servlet specific constructs such as request and session attributes. The following test
|
Servlet specific things such as request and session attributes. The following test
|
||||||
asserts that binding/validation failed:
|
asserts that binding/validation failed:
|
||||||
|
|
||||||
[source,java,indent=0]
|
[source,java,indent=0]
|
||||||
|
@ -4054,8 +4023,8 @@ after all expectations:
|
||||||
// ...
|
// ...
|
||||||
----
|
----
|
||||||
|
|
||||||
When all tests repeat the same expectations, you can define the common expectations once
|
When all tests repeat the same expectations you can set up common expectations once
|
||||||
when building the `MockMvc`:
|
when building the `MockMvc` instance:
|
||||||
|
|
||||||
[source,java,indent=0]
|
[source,java,indent=0]
|
||||||
[subs="verbatim,quotes"]
|
[subs="verbatim,quotes"]
|
||||||
|
|
Loading…
Reference in New Issue