{"id":64,"date":"2016-07-18T12:33:10","date_gmt":"2016-07-18T16:33:10","guid":{"rendered":"http:\/\/computermoose.topshot.com\/?p=64"},"modified":"2016-07-18T12:33:10","modified_gmt":"2016-07-18T16:33:10","slug":"unit-testing-spring-mvc-rest-controllers","status":"publish","type":"post","link":"https:\/\/computermoose.topshot.com\/index.php\/2016\/07\/18\/unit-testing-spring-mvc-rest-controllers\/","title":{"rendered":"Unit Testing Spring MVC REST Controllers"},"content":{"rendered":"<p><span style=\"font-family: arial, helvetica, sans-serif;\">Unit tests are supposed to run against functional methods. \u00a0The method under test is looked upon as a black box with inputs and outputs. \u00a0You define a set of inputs, both legal and illegal, and expect certain outputs or possible exceptions. \u00a0Ideally, you exercise all the different paths within the method.<\/span><\/p>\n<p><span style=\"font-family: arial, helvetica, sans-serif;\">With MVC controllers, there is automatic &#8220;wiring&#8221; that Spring sets up within the controller class. \u00a0The application server (such as tomcat), through the Spring interface, calls the appropriate controller method based on the input path specified in the HTTP request. \u00a0Furthermore, if the data package is a JSON string, the data is automatically converted to an appropriate Java object. \u00a0How do we implement a unit test for this? \u00a0Complete documentation for the Spring MVC Test Framework can be found <a href=\"http:\/\/docs.spring.io\/spring\/docs\/4.3.x\/spring-framework-reference\/htmlsingle\/#spring-mvc-test-framework\">here<\/a>.<\/span><\/p>\n<p><span style=\"font-family: arial, helvetica, sans-serif;\">The example presented below uses the\u00a0following library versions of applicable libraries:<\/span><\/p>\n<table style=\"width: 297px;\">\n<tbody>\n<tr style=\"height: 28px;\">\n<td style=\"width: 10px; height: 28px;\"><span style=\"font-family: arial, helvetica, sans-serif;\"><strong>Library<\/strong><\/span><\/td>\n<td style=\"width: 10px; height: 28px;\"><span style=\"font-family: arial, helvetica, sans-serif;\"><strong>Version<\/strong><\/span><\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"width: 10px; height: 43px;\"><span style=\"font-family: arial, helvetica, sans-serif;\">Spring<\/span><\/td>\n<td style=\"width: 10px; height: 43px;\"><span style=\"font-family: arial, helvetica, sans-serif;\">4.3.0<\/span><\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"width: 10px; height: 43px;\"><span style=\"font-family: arial, helvetica, sans-serif;\">Mockito<\/span><\/td>\n<td style=\"width: 10px; height: 43px;\"><span style=\"font-family: arial, helvetica, sans-serif;\">2.0.78<\/span><\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"width: 10px; height: 28px;\"><span style=\"font-family: arial, helvetica, sans-serif;\">Java<\/span><\/td>\n<td style=\"width: 10px; height: 28px;\"><span style=\"font-family: arial, helvetica, sans-serif;\">1.8<\/span><\/td>\n<\/tr>\n<tr style=\"height: 28px;\">\n<td style=\"width: 10px; height: 28px;\"><span style=\"font-family: arial, helvetica, sans-serif;\">Jackson<\/span><\/td>\n<td style=\"width: 10px; height: 28px;\"><span style=\"font-family: arial, helvetica, sans-serif;\">2.7.2<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-family: arial, helvetica, sans-serif;\">The following pom.xml file is used to define the project:<\/span><\/p>\n<pre style=\"width: 1000px;\">&lt;project xmlns=\"http:\/\/maven.apache.org\/POM\/4.0.0\" xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"\r\n xsi:schemaLocation=\"http:\/\/maven.apache.org\/POM\/4.0.0 http:\/\/maven.apache.org\/maven-v4_0_0.xsd\"&gt;\r\n &lt;modelVersion&gt;4.0.0&lt;\/modelVersion&gt;\r\n &lt;groupId&gt;com.topshot.mvcdemo&lt;\/groupId&gt;\r\n &lt;packaging&gt;war&lt;\/packaging&gt;\r\n &lt;version&gt;1.0-SNAPSHOT&lt;\/version&gt;\r\n &lt;artifactId&gt;MVCDemo&lt;\/artifactId&gt;\r\n &lt;name&gt;MVC Demo App&lt;\/name&gt;\r\n &lt;url&gt;http:\/\/maven.apache.org&lt;\/url&gt;\r\n\r\n &lt;properties&gt;\r\n   &lt;javax.servlet.version&gt;3.1.0&lt;\/javax.servlet.version&gt;\r\n   &lt;jackson.version&gt;2.7.2&lt;\/jackson.version&gt;\r\n   &lt;jdk.version&gt;1.8&lt;\/jdk.version&gt;\r\n   &lt;maven-compiler-plugin.version&gt;2.3.2&lt;\/maven-compiler-plugin.version&gt;\r\n   &lt;maven-eclipse-plugin.version&gt;2.9&lt;\/maven-eclipse-plugin.version&gt;\r\n   &lt;mockito.version&gt;2.0.78-beta&lt;\/mockito.version&gt;\r\n   &lt;spring.version&gt;4.3.0.RELEASE&lt;\/spring.version&gt;\r\n &lt;\/properties&gt;\r\n\r\n &lt;dependencies&gt;\r\n   &lt;!-- Spring dependencies --&gt;\r\n   &lt;dependency&gt;\r\n     &lt;groupId&gt;org.springframework&lt;\/groupId&gt;\r\n     &lt;artifactId&gt;spring-core&lt;\/artifactId&gt;\r\n     &lt;version&gt;${spring.version}&lt;\/version&gt;\r\n   &lt;\/dependency&gt;\r\n\r\n   &lt;dependency&gt;\r\n     &lt;groupId&gt;org.springframework&lt;\/groupId&gt;\r\n     &lt;artifactId&gt;spring-web&lt;\/artifactId&gt;\r\n     &lt;version&gt;${spring.version}&lt;\/version&gt;\r\n   &lt;\/dependency&gt;\r\n\r\n   &lt;dependency&gt;\r\n     &lt;groupId&gt;org.springframework&lt;\/groupId&gt;\r\n     &lt;artifactId&gt;spring-webmvc&lt;\/artifactId&gt;\r\n     &lt;version&gt;${spring.version}&lt;\/version&gt;\r\n   &lt;\/dependency&gt;\r\n\r\n   &lt;!-- Jackson JSON Mapper --&gt;\r\n   &lt;dependency&gt;\r\n     &lt;groupId&gt;com.fasterxml.jackson.core&lt;\/groupId&gt;\r\n     &lt;artifactId&gt;jackson-core&lt;\/artifactId&gt;\r\n     &lt;version&gt;${jackson.version}&lt;\/version&gt;\r\n   &lt;\/dependency&gt;\r\n \r\n   &lt;dependency&gt;\r\n     &lt;groupId&gt;com.fasterxml.jackson.core&lt;\/groupId&gt;\r\n     &lt;artifactId&gt;jackson-databind&lt;\/artifactId&gt;\r\n     &lt;version&gt;${jackson.version}&lt;\/version&gt;\r\n   &lt;\/dependency&gt;\r\n \r\n   &lt;dependency&gt;\r\n     &lt;groupId&gt;com.fasterxml.jackson.core&lt;\/groupId&gt;\r\n     &lt;artifactId&gt;jackson-annotations&lt;\/artifactId&gt;\r\n     &lt;version&gt;${jackson.version}&lt;\/version&gt;\r\n   &lt;\/dependency&gt;\r\n\r\n   &lt;dependency&gt;\r\n     &lt;groupId&gt;javax.servlet&lt;\/groupId&gt;\r\n     &lt;artifactId&gt;javax.servlet-api&lt;\/artifactId&gt;\r\n     &lt;version&gt;${javax.servlet.version}&lt;\/version&gt;\r\n   &lt;\/dependency&gt;\r\n\r\n   &lt;dependency&gt;\r\n     &lt;groupId&gt;org.mockito&lt;\/groupId&gt;\r\n     &lt;artifactId&gt;mockito-core&lt;\/artifactId&gt;\r\n     &lt;version&gt;${mockito.version}&lt;\/version&gt;\r\n   &lt;\/dependency&gt;\r\n\r\n   &lt;dependency&gt;\r\n     &lt;groupId&gt;junit&lt;\/groupId&gt;\r\n     &lt;artifactId&gt;junit&lt;\/artifactId&gt;\r\n     &lt;version&gt;4.12&lt;\/version&gt;\r\n   &lt;\/dependency&gt;\r\n\r\n   &lt;dependency&gt;\r\n     &lt;groupId&gt;org.springframework&lt;\/groupId&gt;\r\n     &lt;artifactId&gt;spring-test&lt;\/artifactId&gt;\r\n     &lt;version&gt;${spring.version}&lt;\/version&gt;\r\n   &lt;\/dependency&gt;\r\n\r\n &lt;\/dependencies&gt;\r\n\r\n &lt;build&gt;\r\n   &lt;finalName&gt;MVCDemo&lt;\/finalName&gt;\r\n   &lt;plugins&gt;\r\n     &lt;plugin&gt;\r\n       &lt;groupId&gt;org.apache.maven.plugins&lt;\/groupId&gt;\r\n       &lt;artifactId&gt;maven-eclipse-plugin&lt;\/artifactId&gt;\r\n       &lt;version&gt;${maven-eclipse-plugin.version}&lt;\/version&gt;\r\n       &lt;configuration&gt;\r\n         &lt;downloadSources&gt;true&lt;\/downloadSources&gt;\r\n         &lt;downloadJavadocs&gt;false&lt;\/downloadJavadocs&gt;\r\n         &lt;wtpversion&gt;2.0&lt;\/wtpversion&gt;\r\n       &lt;\/configuration&gt;\r\n     &lt;\/plugin&gt;\r\n     &lt;plugin&gt;\r\n       &lt;groupId&gt;org.apache.maven.plugins&lt;\/groupId&gt;\r\n       &lt;artifactId&gt;maven-compiler-plugin&lt;\/artifactId&gt;\r\n       &lt;version&gt;${maven-compiler-plugin.version}&lt;\/version&gt;\r\n       &lt;configuration&gt;\r\n         &lt;source&gt;${jdk.version}&lt;\/source&gt;\r\n         &lt;target&gt;${jdk.version}&lt;\/target&gt;\r\n       &lt;\/configuration&gt;\r\n     &lt;\/plugin&gt;\r\n   &lt;\/plugins&gt;\r\n &lt;\/build&gt;\r\n\r\n&lt;\/project&gt;<\/pre>\n<p><span style=\"font-family: arial, helvetica, sans-serif;\">Let&#8217;s start by looking at our controller class and see what it does. \u00a0The request that will initiate the call to getUsers is the path &#8220;\/users&#8221; as seen on line 20 of MainController.java. \u00a0Data to be returned is an array of User objects in JSON format. The conversion of variable &#8216;users&#8217; to JSON format is handled by Spring as a result of the two annotations, @RequestMapping and @ResponseBody (lines 20 and 21).<\/span><\/p>\n<pre style=\"width: 1000px;\">package com.topshot.mvcdemo.controller;\r\n\r\nimport java.util.Arrays;\r\n\r\nimport org.springframework.beans.factory.annotation.Autowired;\r\nimport org.springframework.stereotype.Controller;\r\nimport org.springframework.web.bind.annotation.RequestMapping;\r\nimport org.springframework.web.bind.annotation.RequestMethod;\r\nimport org.springframework.web.bind.annotation.ResponseBody;\r\n\r\nimport com.topshot.mvcdemo.model.User;\r\nimport com.topshot.mvcdemo.service.UserService;\r\n\r\n@Controller\r\npublic class MainController {\r\n\r\n   @Autowired\r\n   private UserService userService;\r\n \r\n   @RequestMapping(value = \"\/users\", method = RequestMethod.GET,\r\n                   produces=\"application\/json\")\r\n   public @ResponseBody User[] getUsers() {\r\n       User[] users = userService.getUsers();\r\n       System.out.println(\"DEBUG users: \" + Arrays.toString(users));\r\n       return users;\r\n   }\r\n\r\n   @RequestMapping(value = \"\/user\/{name}\", method = RequestMethod.GET,  \r\n                   produces=\"application\/json\")\r\n   public @ResponseBody String getUser(@PathVariable String name) {\r\n       return \"The name is \" + name;\r\n   }\r\n}<\/pre>\n<p><span style=\"font-family: arial, helvetica, sans-serif;\">There are two ways we might want to unit test this code. \u00a0Much depends on the real implementation of the UserService getUsers() call within the outer getUsers() call. \u00a0If, as it is likely, userService.getUsers() calls a real database or some other service that needs to be running, then this is not really a unit test, rather it is an integration test that requires external setup to be functional. In this case we would want to mock up the userService.getUsers() call. \u00a0On the other hand, if this method call returns some kind of static information (perhaps from a flat file), then we can call the real method with our unit test. \u00a0I will show how both types of unit tests can be implemented.<\/span><\/p>\n<p><span style=\"font-family: arial, helvetica, sans-serif;\">In our first example, we will exercise MainController.getUsers() leaving the call to userService.getUsers() alone (i.e., we will make a real call to this method). \u00a0Here is the code for the unit test class:<\/span><\/p>\n<pre style=\"width: 1000px;\">package com.topshot.mvcdemo.controller;\r\n\r\nimport static org.junit.Assert.*;\r\n\r\nimport org.junit.Before;\r\nimport org.junit.Test;\r\nimport org.junit.runner.RunWith;\r\nimport org.springframework.beans.factory.annotation.Autowired;\r\nimport org.springframework.http.MediaType;\r\nimport org.springframework.test.context.ContextConfiguration;\r\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\r\nimport org.springframework.test.context.web.WebAppConfiguration;\r\nimport org.springframework.test.web.servlet.MockMvc;\r\nimport org.springframework.test.web.servlet.RequestBuilder;\r\nimport org.springframework.test.web.servlet.ResultActions;\r\nimport org.springframework.test.web.servlet.request.MockMvcRequestBuilders;\r\nimport org.springframework.test.web.servlet.result.MockMvcResultMatchers;\r\nimport org.springframework.test.web.servlet.setup.MockMvcBuilders;\r\nimport org.springframework.web.context.WebApplicationContext;\r\n\r\n \/\/ 1\r\n @RunWith(SpringJUnit4ClassRunner.class)\r\n @ContextConfiguration(locations = {\"classpath:\/mvc-dispatcher-servlet.xml\"})\r\n @WebAppConfiguration\r\n public class MainControllerTest {\r\n\r\n   \/\/ 2\r\n   @Autowired \r\n   WebApplicationContext wac;\r\n \r\n   private MockMvc mockMvc;\r\n \r\n   @Before\r\n   public void setUp() throws Exception {\r\n     \/\/ 3\r\n     mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();\r\n   }\r\n\r\n   @Test\r\n   public void testGetUsers() throws Exception {\r\n     \/\/ 4\r\n     RequestBuilder requestBuilder = \r\n       MockMvcRequestBuilders.get(\"\/users\").accept(new \r\n          MediaType(\"application\", \"json\"));\r\n     \/\/ 5\r\n     ResultActions result = mockMvc.perform(requestBuilder);\r\n     result.andExpect(MockMvcResultMatchers.status().isOk());\r\n     String contentType = \r\n       result.andReturn().getResponse().getContentType();\r\n     \/\/ 6\r\n     assertTrue(\"contentType returned is incorrect.\", \r\n     contentType.contains(\"application\/json\"));\r\n     \/\/ 7\r\n     String jsonData = \r\n       result.andReturn().getResponse().getContentAsString();\r\n     assertNotNull(jsonData, \"No data was returned.\");\r\n     assertTrue(\"Insufficent number of characters returned as data.\", \r\n       jsonData.length() &gt; 2);\r\n     assertTrue(\"This JSON string is supposed to start with '['\", \r\n       jsonData.startsWith(\"[\"));\r\n     assertTrue(\"This JSON string is supposed to end with ']'\", \r\n       jsonData.endsWith(\"]\"));\r\n   }\r\n\r\n   @Test\r\n   public void testBadPath() throws Exception {\r\n     \/\/ 8 \r\n     RequestBuilder requestBuilder = \r\n       MockMvcRequestBuilders.get(\"\/Users\").accept(new \r\n       MediaType(\"application\", \"json\"));\r\n     \/\/ 9\r\n     ResultActions result = mockMvc.perform(requestBuilder);\r\n     result.andExpect(\r\n       MockMvcResultMatchers.status().is4xxClientError());\r\n   }\r\n\r\n   @Test\r\n   public void testGetUser() throws Exception {\r\n     RequestBuilder requestBuilder =    \r\n       MockMvcRequestBuilders.get(\"\/user\/Dracula\")\r\n         .accept(new MediaType(\"application\", \"json\"));\r\n\r\n     ResultActions result = mockMvc.perform(requestBuilder);\r\n     result.andExpect(MockMvcResultMatchers.status().isOk());\r\n     String contentType = \r\n        result.andReturn().getResponse().getContentType();\r\n\r\n     assertTrue(\"contentType returned is incorrect.\",  \r\n        contentType.contains(\"application\/json\"));\r\n\r\n     String jsonData =   \r\n        result.andReturn().getResponse().getContentAsString();\r\n     assertNotNull(jsonData, \"No data was returned.\");\r\n     assertTrue(\"Incorrect response\", \r\n        jsonData.equals(\"The name is Dracula\"));\r\n }\r\n\r\n}<\/pre>\n<p><span style=\"font-family: arial, helvetica, sans-serif;\">The following are comments associated with the above unit test Java code:<\/span><\/p>\n<p><span style=\"font-family: arial, helvetica, sans-serif;\">Note 1: These annotations define\u00a0the wiring harness required to integrate JUnit with Spring MVC. \u00a0In particular, class\u00a0SpringJUnit4ClassRunner provides the interface to the Spring TestContext framework. \u00a0The file mvc-dispatcher-servlet.xml defines the MainController bean and the UserService bean used by MainController.java (contents is shown below) via the @Autowired annotation.<\/span><br \/>\n<span style=\"font-family: arial, helvetica, sans-serif;\"> Note 2: The WebApplicationContext is used in conjunction with the @WebAppConfiguration annotation to define the controller context. Using variable wac, one can retrieve the servlet context as well as other controller related information. Variable mockMvc is the main entry point for the server-side Spring MVC test support framework.<\/span><br \/>\n<span style=\"font-family: arial, helvetica, sans-serif;\">Note 3: This is standard setup code for initializing the mockMvc variable.<\/span><br \/>\n<span style=\"font-family: arial, helvetica, sans-serif;\">Note 4: The request to the getUsers service is built (but not executed) at this point. The HTTP path specified is &#8220;\/users&#8221; and the data to be returned must be JSON data.<\/span><br \/>\n<span style=\"font-family: arial, helvetica, sans-serif;\">Note 5: It is here that the request is executed with the results being returned in the ResultActions variable, result.\u00a0<\/span><br \/>\n<span style=\"font-family: arial, helvetica, sans-serif;\">Note 6: Be careful about using String.equals instead of String contains. \u00a0In my own example, &#8220;application\/json;charset=UTF-8&#8221; was actually returned in variable contentType.<\/span><br \/>\n<span style=\"font-family: arial, helvetica, sans-serif;\">Note 7: Here we verify the content returned from the server. This can be done many ways.<\/span><br \/>\n<span style=\"font-family: arial, helvetica, sans-serif;\">Note 8:\u00a0Note that the RESTful path we are using has an upper-case &#8216;U&#8217; for \/users. \u00a0We don&#8217;t have such a service defined.<\/span><br \/>\n<span style=\"font-family: arial, helvetica, sans-serif;\">Note 9:\u00a0An HTTP 404 error should be returned here.<\/span><\/p>\n<p><span style=\"font-family: arial, helvetica, sans-serif;\">This is the contents of file\u00a0mvc-dispatcher-servlet.xml:<\/span><\/p>\n<pre style=\"width: 1000px;\">&lt;beans xmlns=\"http:\/\/www.springframework.org\/schema\/beans\"\r\n xmlns:context=\"http:\/\/www.springframework.org\/schema\/context\"\r\n xmlns:mvc=\"http:\/\/www.springframework.org\/schema\/mvc\" xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"\r\n xsi:schemaLocation=\"\r\n http:\/\/www.springframework.org\/schema\/beans \r\n http:\/\/www.springframework.org\/schema\/beans\/spring-beans-4.3.xsd\r\n http:\/\/www.springframework.org\/schema\/context \r\n http:\/\/www.springframework.org\/schema\/context\/spring-context-4.3.xsd\r\n http:\/\/www.springframework.org\/schema\/mvc\r\n http:\/\/www.springframework.org\/schema\/mvc\/spring-mvc-4.3.xsd\"&gt;\r\n\r\n &lt;context:component-scan base-package=\r\n       \"com.topshot.proximity.controller\" \/&gt;\r\n\r\n &lt;mvc:annotation-driven \/&gt;\r\n\r\n &lt;bean id=\"userService\"   \r\n       class=\"com.topshot.mvcdemo.service.UserService\"&gt;\r\n &lt;\/bean&gt;\r\n \r\n&lt;\/beans&gt;<\/pre>\n<p><span style=\"font-family: arial, helvetica, sans-serif;\">Let&#8217;s modify our unit test somewhat. Instead of having MainController.getUsers() call the real UserService, we will create a mockup of that service using Mockito. \u00a0Our new unit test code will look like this:<\/span><\/p>\n<pre style=\"width: 1000px;\">\u00a0\r\npackage com.topshot.mvcdemo.controller;\r\n\r\nimport static org.junit.Assert.*;\r\nimport static org.mockito.Mockito.*;\r\n\r\nimport org.junit.Before;\r\nimport org.junit.Test;\r\nimport org.junit.runner.RunWith;\r\nimport org.mockito.InjectMocks;\r\nimport org.mockito.Mock;\r\nimport org.mockito.MockitoAnnotations;\r\nimport org.springframework.http.MediaType;\r\nimport org.springframework.test.context.ContextConfiguration;\r\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\r\nimport org.springframework.test.context.web.WebAppConfiguration;\r\nimport org.springframework.test.web.servlet.MockMvc;\r\nimport org.springframework.test.web.servlet.RequestBuilder;\r\nimport org.springframework.test.web.servlet.ResultActions;\r\nimport org.springframework.test.web.servlet.request.MockMvcRequestBuilders;\r\nimport org.springframework.test.web.servlet.result.MockMvcResultMatchers;\r\nimport org.springframework.test.web.servlet.setup.MockMvcBuilders;\r\n\r\nimport com.topshot.mvcdemo.model.User;\r\nimport com.topshot.mvcdemo.service.UserService;\r\n\r\n @RunWith(SpringJUnit4ClassRunner.class)\r\n @ContextConfiguration(\r\n     locations = {\"classpath:\/mvc-dispatcher-servlet.xml\"})\r\n @WebAppConfiguration\r\n public class MainControllerTest {\r\n\r\n   \/\/ 1\r\n   @InjectMocks\r\n   private MainController mainController;\r\n \r\n   @Mock\r\n   private UserService userService;\r\n\r\n   private MockMvc mockMvc;\r\n \r\n   \/\/ dummy data\r\n   public User [] getUsers() {\r\n     User[] users = {\r\n       new User(\"Bob Dylan\"), \r\n       new User(\"Leonard Cohen\")\r\n     };\r\n     return users;\r\n   }\r\n \r\n   @Before\r\n   public void setUp() throws Exception {\r\n     \/\/ 2\r\n     MockitoAnnotations.initMocks(this);\r\n     mockMvc = MockMvcBuilders.standaloneSetup(mainController).build();\r\n   }\r\n\r\n   @Test\r\n   public void testGetUsers() throws Exception {\r\n     \/\/ 3\r\n     when(userService.getUsers()).thenReturn(getUsers());\r\n\r\n     RequestBuilder requestBuilder =  \r\n       MockMvcRequestBuilders.get(\"\/users\").accept(new \r\n       MediaType(\"application\", \"json\"));\r\n\r\n     ResultActions result = mockMvc.perform(requestBuilder);\r\n     result.andExpect(MockMvcResultMatchers.status().isOk());\r\n     String contentType = \r\n       result.andReturn().getResponse().getContentType();\r\n \r\n     assertTrue(\"contentType returned is incorrect.\", \r\n     contentType.contains(\"application\/json\"));\r\n \r\n     String jsonData = \r\n       result.andReturn().getResponse().getContentAsString();\r\n     assertNotNull(jsonData, \"No data was returned.\");\r\n     assertTrue(\"Insufficent number of characters returned as data.\", \r\n       jsonData.length() &gt; 2);\r\n     assertTrue(\"This JSON string is supposed to start with '['\", \r\n       jsonData.startsWith(\"[\"));\r\n     assertTrue(\"This JSON string is supposed to end with ']'\", \r\n       jsonData.endsWith(\"]\"));\r\n     }\r\n }<\/pre>\n<p><span style=\"font-family: arial, helvetica, sans-serif;\">The following comments point to changes in this copy of the Java unit test code when compared to the original unit test\u00a0code:<\/span><\/p>\n<p><span style=\"font-family: arial, helvetica, sans-serif;\">Note 1: Annotation @InjectMocks is used by Mockito to define the\u00a0Mock injections in the MainController class instance for constructors and methods. Using this annotation simplifies the amount of required test code. See the <a href=\"http:\/\/site.mockito.org\/mockito\/docs\/current\/org\/mockito\/InjectMocks.html\">documentation <\/a>for further information about this class.\u00a0<\/span><br \/>\n<span style=\"font-family: arial, helvetica, sans-serif;\"> Note 2: Method\u00a0MockitoAnnotations.initMocks() does the actual initialization of the Mock objects.<\/span><br \/>\n<span style=\"font-family: arial, helvetica, sans-serif;\">Note 3: This is a standard Mockito when() method. \u00a0Whenever a call is made to UserService.getUsers(), this code is executed instead of the real code. \u00a0<\/span><\/p>\n<p><span style=\"font-family: arial, helvetica, sans-serif;\">File mvc-dispatcher-servlet.xml can also be simplified. \u00a0No bean needs to be specified. \u00a0For the sake of completeness, I&#8217;m including the code for User and UserService:<\/span><\/p>\n<p><span style=\"font-family: arial, helvetica, sans-serif;\">User.java:<\/span><\/p>\n<pre>package com.topshot.mvcdemo.model;\r\n\r\npublic class User {\r\n\r\n String name;\r\n\r\n public User(String name) {\r\n   this.name = name;\r\n }\r\n \r\n public String getName() {\r\n   return name;\r\n }\r\n\r\n public void setName(String name) {\r\n   this.name = name;\r\n }\r\n}<\/pre>\n<p><span style=\"font-family: arial, helvetica, sans-serif;\">UserService.java:<\/span><\/p>\n<pre>package com.topshot.mvcdemo.service;\r\n\r\nimport com.topshot.mvcdemo.model.User;\r\n\r\npublic class UserService {\r\n\r\n   User[] people = {\r\n     new User(\"Barak Obama\"), \r\n     new User(\"George Bush\"),\r\n     new User(\"Bill Clinton\"),\r\n     new User(\"Abraham Lincoln\")\r\n   }; \r\n \r\n   public User[] getUsers() {\r\n     \/\/ Get data from DB or wherever\r\n     return people;\r\n }\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Unit tests are supposed to run against functional methods. \u00a0The method under test is looked upon as a black box with inputs and outputs. \u00a0You define a set of inputs, both legal and illegal, and expect certain outputs or possible exceptions. \u00a0Ideally, you exercise all the different paths within the method. With MVC controllers, there &hellip; <a href=\"https:\/\/computermoose.topshot.com\/index.php\/2016\/07\/18\/unit-testing-spring-mvc-rest-controllers\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Unit Testing Spring MVC REST Controllers&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[1],"tags":[],"class_list":["post-64","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p7qelO-12","jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/computermoose.topshot.com\/index.php\/wp-json\/wp\/v2\/posts\/64","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/computermoose.topshot.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/computermoose.topshot.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/computermoose.topshot.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/computermoose.topshot.com\/index.php\/wp-json\/wp\/v2\/comments?post=64"}],"version-history":[{"count":13,"href":"https:\/\/computermoose.topshot.com\/index.php\/wp-json\/wp\/v2\/posts\/64\/revisions"}],"predecessor-version":[{"id":77,"href":"https:\/\/computermoose.topshot.com\/index.php\/wp-json\/wp\/v2\/posts\/64\/revisions\/77"}],"wp:attachment":[{"href":"https:\/\/computermoose.topshot.com\/index.php\/wp-json\/wp\/v2\/media?parent=64"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/computermoose.topshot.com\/index.php\/wp-json\/wp\/v2\/categories?post=64"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/computermoose.topshot.com\/index.php\/wp-json\/wp\/v2\/tags?post=64"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}