[[mockmvc-vs-end-to-end-integration-tests]]
= MockMvc vs End-to-End Tests

MockMvc is built on Servlet API mock implementations from the
`spring-test` module and does not rely on a running container. Therefore, there are
some differences when compared to full end-to-end integration tests with an actual
client and a live server running.

The easiest way to think about this is by starting with a blank `MockHttpServletRequest`.
Whatever you add to it is what the request becomes. Things that may catch you by surprise
are that there is no context path by default; no `jsessionid` cookie; no forwarding,
error, or async dispatches; and, therefore, no actual JSP rendering. Instead,
"forwarded" and "redirected" URLs are saved in the `MockHttpServletResponse` and can
be asserted with expectations.

This means that, if you use JSPs, you can verify the JSP page to which the request was
forwarded, but no HTML is rendered. In other words, the JSP is not invoked. Note,
however, that all other rendering technologies which do not rely on forwarding, such as
Thymeleaf and Freemarker, render HTML to the response body as expected. The same is true
for rendering JSON, XML, and other formats through `@ResponseBody` methods.

Alternatively, you may consider the full end-to-end integration testing support from
Spring Boot with `@SpringBootTest`. See the
{spring-boot-docs}/spring-boot-features.html#boot-features-testing[Spring Boot Reference Guide].

There are pros and cons for each approach. The options provided in Spring MVC Test are
different stops on the scale from classic unit testing to full integration testing. To be
certain, none of the options in Spring MVC Test fall under the category of classic unit
testing, but they are a little closer to it. For example, you can isolate the web layer
by injecting mocked services into controllers, in which case you are testing the web
layer only through the `DispatcherServlet` but with actual Spring configuration, as you
might test the data access layer in isolation from the layers above it. Also, you can use
the standalone setup, focusing on one controller at a time and manually providing the
configuration required to make it work.

Another important distinction when using Spring MVC Test is that, conceptually, such
tests are server-side tests, so you can check what handler was used, if an exception was
handled with a `HandlerExceptionResolver`, what the content of the model is, what binding
errors there were, and other details. That means that it is easier to write expectations,
since the server is not an opaque box, as it is when testing it through an actual HTTP
client. This is generally an advantage of classic unit testing: it is easier to write,
reason about, and debug but does not replace the need for full integration tests. At the
same time, it is important not to lose sight of the fact that the response is the most
important thing to check. In short, there is room for multiple styles and strategies
of testing even within the same project.

