If you're interested in JUnit
testing your Spring
MVC
controllers, feel free to visit Github
repo
containing very simple example of Spring
MVC
controller and JUnit
test class testing it's endpoints. Project is implemented
using Spring Boot
framework.
The controller part looks like this:
package rs.dodalovic.demos.category;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Optional;
@RestController
@RequestMapping("/categories")
public class CategoriesController {
private CategoryService categoryService;
@RequestMapping
public List<String> allCategories() {
return categoryService.getAllCategories();
}
@RequestMapping(value = "/{categoryId}", method = RequestMethod.GET)
public ResponseEntity<String> showCategory(@PathVariable("categoryId") String categoryId) {
final Optional<String> category = categoryService.getCategory(categoryId);
if (category.isPresent()) {
return ResponseEntity.ok(category.get());
}
return ResponseEntity.badRequest().body(categoryId);
}
@RequestMapping(method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Void> createCategory(@RequestBody Category category) throws
URISyntaxException {
return ResponseEntity.created(new URI("http://localhost/categories/1")).body(null);
}
@Autowired
public CategoriesController(CategoryService categoryService) {
this.categoryService = categoryService;
}
}
There's no special functionality, it uses CategoryService
to fetch some data. Also, exposes http
endpoints (showCategory
,
createCategory
) we'll exercise in our test class, which is given below:
package rs.dodalovic.demos.category;
import org.hamcrest.core.StringContains;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.http.MediaType;
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.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import rs.dodalovic.demos.DemoApplication;
import java.util.Optional;
import static java.util.Arrays.asList;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = DemoApplication.class)
@ContextConfiguration(classes = MockServletContext.class)
@WebAppConfiguration
public class CategoriesControllerTest {
private MockMvc mockMvc;
private CategoryService categoryService;
@Before
public void beforeEachTest() {
categoryService = mock(CategoryService.class);
given(categoryService.getAllCategories()).willReturn(asList("Category 1", "Category 2", "Category 3"));
mockMvc = MockMvcBuilders.standaloneSetup(new CategoriesController(categoryService)).build();
}
@Test
public void allCategories() throws Exception {
mockMvc.perform(
MockMvcRequestBuilders.get("/categories")
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().string("[\"Category 1\",\"Category 2\",\"Category 3\"]"));
}
@Test
public void asserts404ForNotExistingCategory() throws Exception {
given(categoryService.getCategory("-1")).willReturn(Optional.empty());
mockMvc.perform(
MockMvcRequestBuilders.get("/categories/-1")
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().is4xxClientError());
}
@Test
public void assertsCategoryFound() throws Exception {
given(categoryService.getCategory("1")).willReturn(Optional.of("Category 1"));
mockMvc.perform(
MockMvcRequestBuilders.get("/categories/1")
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(content().string("Category 1"));
}
@Test
public void postForbiddenToGetCategory() throws Exception {
given(categoryService.getCategory("1")).willReturn(Optional.of("Category 1"));
mockMvc.perform(
MockMvcRequestBuilders.post("/categories/1")
.accept(MediaType.APPLICATION_JSON))
.andExpect(status().isMethodNotAllowed());
}
@Test
public void createsCategory() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.post("/categories")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"name\":\"Category\"}")
).andExpect(status().isCreated())
.andExpect(header().string("location", new StringContains("/categories/")));
}
}
For those familiar with JUnit
testing concept this should not be hard to understand. For the beginners - I suggest reading
my earlier post. Basic idea is to
mock dependency our controller class has, performing HTTP
call, and asserting HTTP
status, body, headers etc...
Once more, GitHub repo with sources.
That was all for today! Hope you liked it!