This blog post is the first part of my Spring MockMvc tutorial. This tutorial describes how we can write unit and integration tests for Spring MVC controllers by using Spring Boot 4, Spring Framework 7, and JUnit Jupiter. However, before we can write any test code, we have to understand the basics.
After we have finished this blog post, we:
- Understand what Spring MockMvc is.
- Can identify the key components of Spring MockMvc.
- Know how we can get the required dependencies with Maven and Gradle.
Let's begin.
What Is Spring MockMvc?
Spring MockMvc is a testing tool which provides support for testing Spring MVC controllers. The benefits of Spring MockMvc are:
- No Web Server Required. Because Spring MockMvc is built on top of the Servlet API mock objects provided by the
spring-testmodule, it doesn't require a servlet container and the tests which use it bypass the network layer. Thus, our tests are as fast as possible. - Full Spring MVC Runtime Support. Because Spring MockMvc uses the
DispatcherServletclass that provides full support for the Spring MVC runtime behavior, we can test real request mappings, parameter binding, request validation, error handling, and JSON serialization/deserialization. - Test Framework Agnostic. We can write our tests by using JUnit 4, JUnit 5, or TestNG. We can also use other testing frameworks as long as the testing framework provides support for Spring MockMvc or we use the standalone configuration.
- Flexible Test Configuration. We can configure the system under test by using a lightweight standalone configuration, a focused test slice (
@WebMvcTest), or a web application context based configuration. We will talk more about these configuration options in the next posts of this tutorial. - Flexible Assertion Support. We can write assertions by using Spring's
MockMvcResultMatchers(together with Hamcrest or JSONPath), write assertions for theMvcResultobject by using our favorite assertion library, or leverage the fluentMockMvcTesterAPI and write our assertions with AssertJ.
Next, we will take a look at the key components of Spring MockMvc.
The Key Components of Spring MockMvc
Spring MockMvc provides two main styles for writing tests:
- The Classic
MockMvcAPI which uses static factory methods. - The Modern
MockMvcTesterAPI which was introduced in Spring Framework 6.2 / Spring Boot 3.4. TheMockMvcTesterAPI provides a fluent API for sending HTTP requests to the system under test and integrates Spring MockMvc with AssertJ.
Let's move on and take a look at the core components of both styles.
The Classic MockMvc API
If we use the traditional MockMvc API, our tests will interact with the following key classes:
- The
MockMvcclass acts as an entry point for our unit and integration tests. To be more specific, we will use this class when we send HTTP requests to the system under test. - The
MockMvcBuildersclass providesstaticfactory methods which allow us to create newMockMvcobjects. - The
MockMvcRequestBuildersclass providesstaticfactory methods which we can use for creating the HTTP requests sent to the system under test. - The
MockMvcResultMatchersclass providesstaticfactory methods which allow us to write assertions for the returned HTTP response. - The
MockMvcResultHandlersclass providesstaticfactory methods which we can use when we want to print the returned HTTP response or write the HTTP response to a log file by using the Apache Commons Logging library.
The Modern MockMvcTester API
If we use the modern MockMvcTester API, our tests will interact with the following key classes:
- The
MockMvcTesterclass is built on top of theMockMvcAPI. It provides a fluent API for building HTTP requests and sending them to the system under test. - The
MvcTestResultclass contains the result of an executed HTTP request that was built with theMockMvcTesterAPI. We can write assertions for the HTTP response by invoking theassertThat()method and passing theMvcTestResultobject as a method parameter. - The
MvcTestResultAssertclass implements the AssertJ assertions which we can use when we are writing assertions for the returned HTTP response.
Let's move on and find out how we can get the required dependencies with Maven and Gradle.
Getting the Required Dependencies
This section describes how we can get the required dependencies when we declare our dependencies one by one and when we use the dependency management of Spring Boot.
Declaring Our Dependencies One by One
If we are building a standalone Spring application without Spring Boot, we must declare the spring-test dependency in our build script.
If we are using Maven, we can declare this dependency by adding the following snippet to the dependencies section of our pom.xml file:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>7.0.8</version>
<scope>test</scope>
</dependency>
If we are using Gradle, we have to add the spring-test dependency to the testImplementation dependency configuration.
If we are using the Groovy DSL, we have to add the following snippet to the dependencies block of our build.gradle file:
testImplementation('org.springframework:spring-test:7.0.8')
If we are using the Kotlin DSL, we have to add the following snippet to the dependencies block of our build.gradle.kts file:
testImplementation("org.springframework:spring-test:7.0.8")
Using the Dependency Management of Spring Boot
If we use Spring Boot, we only need to declare the spring-boot-starter-test dependency in our build script. The dependency management of Spring Boot will automatically get compatible versions of all essential testing libraries (including JUnit Jupiter, Mockito, AssertJ, and Spring Test).
If we are using Maven, we can declare this dependency by adding the following snippet to the dependencies section of our pom.xml file:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
If we are using Gradle, we have to add the spring-boot-starter-test dependency to the testImplementation dependency configuration.
If we are using the Groovy DSL, we have to add the following snippet to the dependencies block of our build.gradle file:
testImplementation('org.springframework.boot:spring-boot-starter-test')
If we are using the Kotlin DSL, we have to add the following snippet to the dependencies block of our build.gradle.kts file:
testImplementation("org.springframework.boot:spring-boot-starter-test")
Let's summarize what we learned from this blog post.
Summary
This blog post has taught us five things:
- Spring MockMvc doesn't require a servlet container and the tests which use it bypass the network layer.
- Spring MockMvc provides full support for the Spring MVC runtime behavior because it uses the real
DispatcherServletclass behind the scenes. - The classic
MockMvcuses static builders and matchers and the modernMockMvcTesterprovides a fluent API with AssertJ integration. - If we are building a standalone Spring application without Spring Boot, we must declare the
spring-testdependency in our build script. - If we use Spring Boot, we only need to declare the
spring-boot-starter-testdependency in our build script.
Written very simply and clearly. Thanks!
You are welcome!
good article to understand,it is very clear,i love it
by the way,i am a chinese programmer young man。even if my English is poor,but i also can understand easily。so your article is good。
Thank you for your kind words. I really appreciate them! If you liked this article, you should take a look at my Spring MVC Test (aka
MockMvc) Tutorial.