Unit Testing Spring REST Controllers Via Mock MVC

Phoenix Rising
2 min readOct 1, 2018

--

I would start off with a disclaimer that REST based controllers are better tested using integration tests or using a more suitable mocking framework like wiremock.

However, assuming that you may still want to use Mock MVC in your junit tests, we can do something like the following:

1.) Let us say we want to test a (super simplifed) controller that looks something like:


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/fizzbuzz/v1/*")
public class MyController {

private SomeComponent bean;

@Autowired
public void setBean(SomeComponent bean) {
this.bean = bean;
}

@RequestMapping(value="/action" , method = {RequestMethod.POST})
public ResponseEntity<?> execute()
{

bean.setState("CREATED");
return ResponseEntity.ok().build();
}


}

The “SomeComponent” in the above example is managed by Spring (using the “@Component” annotation).

2.) The gradle dependencies that we will require are:

// Use JUnit test framework
testImplementation 'junit:junit:' + "${junitVersion}"
testCompile group: 'org.mockito', name: 'mockito-core', version: "${mockitoCoreVersion}"
testCompile group: 'org.springframework', name: 'spring-test', version: "${springTestVersion}"
testCompile group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: "${springBootStarterTestVersion}"

3.) The test class will look something like:


import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;

import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.verify;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@RunWith(SpringJUnit4ClassRunner.class)
public class LCMControllerTest {

@InjectMocks
private MyController controllerUnderTest;

@Spy
private SomeComponent bean;


private MockMvc mockMvc;

@Before
public void startService() throws Exception{
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders.standaloneSetup(controllerUnderTest).build();
}

@Test
public void testExecute()throws Exception{
mockMvc.perform(post("http://<base_url>/fizzbuzz/v1/action"))
.andDo(print())
.andExpect(status().isOk());
verify(bean,atLeastOnce()).setState("CREATED");
}
}

Obviously, this is a very simplified example and essentially illustrates the bare bones of mock mvc usage in junit tests. This however can be used to build unit tests around REST controllers.

--

--