Spring Boot Integration Testing with MockMvc
Tags: mockmvc, spring, java, junit
Published: 2022-10-22 14:29:34

In this piece, we will build a REST-ful API using Spring Boot and Spring MVC, then perform integration testing by making requests to our endpoints and verifying the responses. For this project, we will need JUnit, MockMvc, H2, and a few other dependencies. Let's get started!<h2 style="text-align: left;">Dependencies</h2><div>First, go to the <a href="https://start.spring.io" target="_blank">Spring Initializr</a>&nbsp;and generate a Spring Web application using the following dependencies:</div><div><ol style="text-align: left;"><li>Spring Web</li><li>Spring Data JPA</li><li>H2 Database</li><li>Lombok</li></ol>

![Configuring Spring Boot dependencies with Spring Initializr](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0mzx3gdywo4gthaq5otd.png)

</div><div><br /></div>We will create a REST-ful API, expose some endpoints, and test those endpoints using MockMvc.<div>For persistence support, we will use the H2 in-memory database, and for interacting with the database, we will use the repositories provided by Spring Data JPA. I will be using Lombok for reducing the amount of boilerplate code I would be writing otherwise.</div><h2 style="text-align: left;">Controllers</h2><div>For the purposes of brevity, we will be exposing just the following endpoints and HTTP actions:</div><div><ol style="text-align: left;"><li><b>GET /batteries</b>&nbsp;- Returns a list of all Battery resources in database</li><li><b>GET /batteries/:id</b> - Returns the Battery resource identified by id path variable</li><li><b>POST /batteries</b> - Persists a Battery resource in database and returns the persisted resource</li></ol><h2 style="text-align: left;">Resource</h2><div>As you can see from the Controllers section, we will be working on a Battery resource for our API. The Battery resource will have the following fields:</div>
<div>{% gist https://gist.github.com/roshanadh/b2a3ed7bea790dafc83c2e1ccf6fe56d.js %}Also, using the JPA annotations @Entity, @Table, @Column, etc., we map the POJO to our database entity of name <em>batteries</em>.</div><h2 style="text-align: left;">Repository</h2><div>One of the most useful features of the Spring Data JPA project is the Repository pattern that comes with its implementations out-of-the-box. This way, we can quickly bootstrap a CRUD functionality without having to writing queries by ourselves.</div><div><br /></div><div>Let us define the repository for our Battery entity by extending the <em>JpaRepository </em>interface.</div><div><br /></div>
<div>{% gist https://gist.github.com/roshanadh/392ae712253cab52f29ced8ca322a207.js %}</div>
<div>Having defined this repository, we can now access a bunch of predefined methods that implement CRUD functionality (e.g.,&nbsp; <em>save</em>, <em>saveAll</em>, <em>deleteById</em>, <em>delete</em>, etc.)</div><h2 style="text-align: left;">Bootstrap the database</h2><div>To test our application, we will need some preloaded records. Let us create a Bootstrap configuration class that loads records into our database every time the application starts.</div> 
<div>{% gist https://gist.github.com/roshanadh/8f2756543befe9e0a1d9c385096bd32b.js %}When a class is annotated with <em>@Configuration</em>, it means that the Spring IOC container can expect some bean definition inside the class. And so we give a bean definition using the <em>@Bean</em>&nbsp;annotation on the <em>initDb </em>method that returns an object of type <em>CommandLineRunner</em>.</div><br /><blockquote><em>CommandLineRunner </em>is a functional interface with a method named&nbsp;<em>run</em>. When the Spring context is loaded, Spring Boot invokes the run method of all beans of type <em>CommandLineRunner</em>.</blockquote>

<h2 style="text-align: left;">Application properties</h2><div>For our application to work, we need to pass some application properties, including those for the database URL, username, password, and driver class name. Additionally, you can pass properties to enable the H2 console through which you can access the database using a GUI.</div>
<div>{% gist https://gist.github.com/roshanadh/5a54b4c9a34e03046c5f85e15d163e1d.js %}</div>
  <h2 style="text-align: left;">Testing our API</h2><div>The <em>spring-boot-starter-test</em> starter module included in our <em>pom.xml</em> file includes <em>JUnit</em>, <em>AssertJ</em>, <em>Hamcrest</em>, etc. All of these libraries help us write effective test cases for our projects.</div><div><br /></div><div>For this particular project, start with the main test class:</div><div><br /></div>
<div>{% gist https://gist.github.com/roshanadh/1c27fdbc1b1ed0070b84acea8ca4e924.js %}</div>
  <div>The <em>@SpringBootTest</em>&nbsp;annotation is used on tests classes for Spring Boot, and it loads the complete Spring application context.</div><div><br /></div><div>Using <em>@AutoConfigureMockMvc</em>, we can enable auto-configuration of the Spring MVC test framework. <em>MockMvc </em>does request handling but uses mock request and response objects. No actual server is started.</div><h3 style="text-align: left;">Testing GET /batteries/:id</h3>
<div>{% gist https://gist.github.com/roshanadh/8dc3e4180d8267c7f5d2312f7a5679b1.js %}</div>
  <div>As you can see, we have imported some static methods from MockMvcRequestBuilders, MockMvcResultHandlers, and MockMvcResultMatchers. These static methods are then used for making HTTP requests (<em>get</em>, <em>post</em>, etc.), reading JSON responses (<em>jsonPath</em>), and printing the responses (<em>print</em>).</div><div><br /></div><div>With the above test case, we verify that the response for <em>GET /batteries/1</em> HTTP action contains the same <em>id</em>, <em>name</em>, <em>postcode</em>, and <em>capacity</em> values as in our database (the one we preloaded).</div><h3 style="text-align: left;">Testing GET /batteries</h3>
<div>{% gist https://gist.github.com/roshanadh/9bfe40594ca273d3bd2be0f545d5da3a.js %}</div>
  <div>Similar to the previous test, we make a GET request to our endpoint and then print the response. Then we continue our tests through&nbsp;<em>andExpect</em>. First, we verify that the response status is <em>200 OK</em>. Then, we verify that the response is a list of JSON objects. Finally, we verify that the size of list is equal to the size of records that exist in the database.</div><h3 style="text-align: left;">Testing POST /batteries</h3>
<div>{% gist https://gist.github.com/roshanadh/5fc60b30b13e80326562f8e865e37f8e.js %}</div>
  <div>To send a request body along with our POST request, we use the autowired&nbsp;<em>ObjectMapper</em>&nbsp;instance to map the Battery object onto a String. The string object is then passed as the content of our POST request, and we specify the type of request body as JSON using <em>contentType </em>method.</div><div><br /></div><div>Then, we use <em>andExpect </em>to verify our expectations with the JSON response. The response status should should be <em>201 CREATED</em>. And since our API returns the very object that was persisted, the <em>name</em>, <em>postcode</em>, and <em>capacity </em>parameters should match.</div><h2 style="text-align: left;">Conclusion</h2><div>We have successfully created and tested our REST-ful API using <em>MockMvc </em>and several other utility testing libraries. The full project code has been pushed to <a href="https://github.com/roshanadh/spring-mockmvc-test" target="_blank">GitHub</a>, feel free to check it out.</div>
</div></div>