Testing a Rest API in Spring Framework

After you have designed your Rest API and implemented it successfully, you need to test it. Testing a Rest Api is not easy because of the application context. By default, to be able to run tests, the Spring MVC container needs to be launched as it contains all of the components that the application needs to run properly ( request mapping, exception handling, …). However, launching the container will take a considerable amount of time slowing down tests. Usually, tests need to run quicker than the application.
To solve this issue, Spring test provides the speed of an out of container context with only the needed infrastructure of Spring MVC. All the infrastructure that we need to run our tests is bootstrapped in an out of container process. That is to say, we get a standalone web application that does not need to run inside a servlet, which allows unit and integration tests to run quicker. In this tutorial, we will go through how to use spring-test for testing a Rest API in Spring framework.

Requirements:

We have the following end points that we want to test:

POST: /person
GET: /person/{id}
GET: /person/{id}/profile
GET: /person/{id}/account

Our test class looks like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations={"classpath:beans.xml"})
public class PersonControllerUnitTest {
	    @Autowired
	    private volatile WebApplicationContext webApplicationContext;

	    private volatile MockMvc mockMvc;

	    @Before
	    public void before() {
	        this.mockMvc = webAppContextSetup(this.webApplicationContext).build();
	    }
	    
	    @Test
	    public void createPersonTest() throws Exception{
	    	this.mockMvc.perform(post("/person"))
	        .andExpect(status().isCreated());
	    }
	    
	    @Test
		public void getPerson() throws Exception{
			this.mockMvc.perform(get("/person/{id}", 1))
			.andExpect(status().isOk())
			.andExpect(content().contentType("application/json;charset=UTF-8"))
			.andExpect(jsonPath("$.firstname").value("John"));
		}
		
		@Test
		public void getProfile() throws  Exception{
			this.mockMvc.perform(get("/person/{id}/profile", 1))
			.andExpect(status().isOk())
			.andExpect(content().contentType("application/json;charset=UTF-8"))
			.andExpect(jsonPath("$.description").value("Profile description"));
		}
		
		@Test
		public void getAccount() throws Exception{
			this.mockMvc.perform(get("/person/{id}/account", 1))
			.andExpect(status().isOk())
			.andExpect(content().contentType("application/json;charset=UTF-8"))
			.andExpect(jsonPath("$.username").value("johnk"));
		}

}

Before running tests, we have configured the application context and initialized a MockMvc object that mimics a Spring MVC infrastructure. Assertions were made on the return HTTP status, the content type, and also on the data returned.