Spring MVC Test Using MockMVC

spring-mvc-view The goal of Spring MVC Test is to provide an effective way for testing controllers. Spring MVC Test allows performing requests and generating responses without the need for running in a Servlet container. It uses the DispatcherServlet to provide full Spring MVC runtime behavior and provides support for loading 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.

Overview

We will build a simple Spring MVC controller that returns JSON content when receiving GET request. In order to build the service we need the following Java classes and XML files:

spring-mvc-test-files

  • Controller.java : Simple Spring MVC controller responding to GET request mapped to /rest/api/get.
  • Link.java: Simple Java model class.
  • rest-servlet: Spring XML configuration file.
  • web.xml: Defining DispatcherServlet.
  • index.html: HTML file with one link calling REST service.
  • TestController: Test class for testing our controller.
  • rest-servlet-test.xml: Spring Configration for testing.
  • pom.xml: Maven pom.xml file listing dependencies and plugin used for this project.

Dependencies

To develop, run and test the service you need the following libraries:

  • Spring Framework

<spring.version>5.0.8.RELEASE</spring.version>


<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context</artifactId>
	<version>${spring.version}</version>
</dependency>

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-core</artifactId>
	<version>${spring.version}</version>
</dependency>

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-beans</artifactId>
	<version>${spring.version}</version>
</dependency>

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-web</artifactId>
	<version>${spring.version}</version>
</dependency>

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-webmvc</artifactId>
	<version>${spring.version}</version>
</dependency>

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-expression</artifactId>
	<version>${spring.version}</version>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>${spring.version}</version>
    <scope>test</scope>
</dependency>
  • jUnit

<junit.version>4.12</junit.version>

<dependency>
	<groupId>junit</groupId>
	<artifactId>junit</artifactId>
	<version>${junit.version}</version>
	<scope>test</scope>
</dependency>
  • hamcrest && jsonpath

Hamcrest and JSON path will be used to assert JSON results

<dependency>
	<groupId>org.hamcrest</groupId>
	<artifactId>hamcrest-library</artifactId>
	<version>1.3</version>
	<scope>test</scope>
</dependency>
<dependency>
	<groupId>com.jayway.jsonpath</groupId>
	<artifactId>json-path</artifactId>
	<version>2.2.0</version>
	<scope>test</scope>
</dependency>

Complete Maven dependencies is included in pom.xml

Spring MVC Controller

We will build a simple controller that returns JSON. The service will return a single Link object in json format.

Controller.java

package com.hmkcode.controllers;


import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.hmkcode.model.Link;

@RestController
@RequestMapping("api")
public class Controller {
	
	@RequestMapping(value = "/get", method = RequestMethod.GET)
	public @ResponseBody Link get(){
		System.out.println("Get!");
		
		Link link = new Link();
		link.setTitle("HMKCODE BLOG!");
		link.setUrl("hmkcode.com");
		
		return link;
		
	}
}

Link.java


package com.hmkcode.model;

public class Link {

	private String title;
	private String url;

	// setters & getters
}

rest-servlet.xml web.xml index.html

Spring MVC Test

TestController.java

  • @RunWith(SpringJUnit4ClassRunner.class) will run Spring test.
  • @ContextConfiguration loads the context configuration in rest-servlet-test.xml.
  • @WebAppConfiguration will load the web application context
package com.hmkcode.test;

import javax.servlet.ServletContext;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockServletContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "/rest-servlet-test.xml")
@WebAppConfiguration
public class TestController {

	@Autowired
	private WebApplicationContext wac;
	
	private MockMvc mockMvc;
	@Before
	public void setup() throws Exception {
	    this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
	}
	
	@Test
	public void configTest() {
	    ServletContext servletContext = wac.getServletContext();
	     
	    Assert.assertNotNull(servletContext);
	    Assert.assertTrue(servletContext instanceof MockServletContext);
	    Assert.assertNotNull(wac.getBean("controller"));
	}
	
	@Test
	public void test() throws Exception{
		 this.mockMvc.perform(get("/api/get"))
		 	.andExpect(status().isOk())
		 	.andDo(print());
		 
	}
}

Source Code @ GitHub