{"id":15087,"date":"2013-07-05T01:00:03","date_gmt":"2013-07-04T22:00:03","guid":{"rendered":"http:\/\/www.javacodegeeks.com\/?p=15087"},"modified":"2013-07-04T12:02:50","modified_gmt":"2013-07-04T09:02:50","slug":"unit-testing-of-spring-mvc-controllers-configuration-2","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2013\/07\/unit-testing-of-spring-mvc-controllers-configuration-2.html","title":{"rendered":"Unit Testing of Spring MVC Controllers: Configuration"},"content":{"rendered":"<p>Writing unit tests for Spring MVC controllers has traditionally been both simple and problematic. Although it is pretty simple to write unit tests which invoke controller methods, the problem is that those unit tests are not comprehensive enough. For example, we cannot test controller mappings, validation and exception handling just by invoking the tested controller method.<\/p>\n<p><a href=\"http:\/\/static.springsource.org\/spring\/docs\/3.2.x\/spring-framework-reference\/htmlsingle\/#new-in-3.2-spring-mvc-test\" target=\"_blank\">Spring MVC Test<\/a> solved this problem by giving us the possibility to invoke controller methods through the <em>DispatcherServlet<\/em>. This is the first part of my tutorial which describes the unit testing of Spring MVC controllers and it describes how we can configure our unit tests. Let\u2019s get started.<\/p>\n<h2>Getting the Required Dependencies with Maven<\/h2>\n<p>We can get the required dependencies by declaring the following testing dependencies in our <em>pom.xml<\/em> file:<\/p>\n<ul>\n<li>JUnit 4.11<\/li>\n<li>Mockito Core 1.9.5<\/li>\n<li>Spring Test 3.2.3.RELEASE<\/li>\n<\/ul>\n<p>The relevant part of our <em>pom.xml<\/em> file looks as follows:<\/p>\n<pre class=\"brush:xml\">&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.11&lt;\/version&gt;\r\n    &lt;scope&gt;test&lt;\/scope&gt;\r\n&lt;\/dependency&gt;\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;1.9.5&lt;\/version&gt;\r\n    &lt;scope&gt;test&lt;\/scope&gt;\r\n&lt;\/dependency&gt;\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;3.2.3.RELEASE&lt;\/version&gt;\r\n    &lt;scope&gt;test&lt;\/scope&gt;\r\n&lt;\/dependency&gt;<\/pre>\n<p>Let\u2019s move on and take a quick look at our example application.<\/p>\n<h2>The Anatomy of Our Example Application<\/h2>\n<p>The example application of this tutorial provides CRUD operations for todo entries. In order to understand the configuration of our test class, we must have some knowledge about the tested controller class.<\/p>\n<p>At this point, we need to know the answers to these questions:<\/p>\n<ul>\n<li>What dependencies does it have?<\/li>\n<li>How is it instantiated?<\/li>\n<\/ul>\n<p>We can get the answers to those questions by taking a look at the source code of the <em>TodoController<\/em> class. The relevant part of the <em>TodoController<\/em> class looks as follows:<\/p>\n<pre class=\"brush:java\">import org.springframework.beans.factory.annotation.Autowired;\r\nimport org.springframework.context.MessageSource;\r\nimport org.springframework.stereotype.Controller;\r\n\r\n@Controller\r\npublic class TodoController {\r\n\r\n    private final TodoService service;\r\n\r\n    private final MessageSource messageSource;\r\n\r\n    @Autowired\r\n    public TodoController(MessageSource messageSource, TodoService service) {\r\n        this.messageSource = messageSource;\r\n        this.service = service;\r\n    }\r\n\r\n    \/\/Other methods are omitted.\r\n}<\/pre>\n<p>As we can see, our controller class has two dependencies: <em>TodoService<\/em> and <em>MessageSource<\/em>. Also, we can see that our controller class uses constructor injection.<\/p>\n<p>At this point this is all there information we need. Next we will talk about our application context configuration.<\/p>\n<h2>Configuring the Application Context<\/h2>\n<p>Maintaining a separate application context configurations for our application and our tests is cumbersome. Also, It can lead into problems if we change something in the application context configuration of our application but forget to do the same change for our test context.<\/p>\n<p>That is why the application context configuration of the example application has been divided in a such way that we can reuse parts of it in our tests.<\/p>\n<p>Our application context configuration has been divided as follows:<\/p>\n<ul>\n<li>The first application configuration class is called <em>ExampleApplicationContext<\/em> and it is the \u201cmain\u201d configuration class of our application.<\/li>\n<li>The second configuration class is responsible of configuring the web layer of our application. The name of this class is <em>WebAppContext<\/em> and it is the configuration class which we will use in our tests.<\/li>\n<li>The third configuration class is called <em>PersistenceContext<\/em> and it contains the persistence configuration of our application.<\/li>\n<\/ul>\n<p><strong>Note:<\/strong> The example application has also a working application context configuration which uses XML configuration files. The XML configuration files which correspond with the Java configuration classes are: <em>exampleApplicationContext.xml<\/em>, exampleApplicationContext-web.xml and <em>exampleApplicationContext-persistence.xml<\/em>.<\/p>\n<p>Let\u2019s take a look at the application context configuration of our web layer and find out how we can configure our test context.<\/p>\n<h3>Configuring the Web Layer<\/h3>\n<p>The application context configuration of the web layer has the following responsibilities:<\/p>\n<ol>\n<li>It enables the annotation driven Spring MVC.<\/li>\n<li>It configures the location of static resources such as CSS files and Javascript files.<\/li>\n<li>It ensures that the static resources are served by the container\u2019s default servlet.<\/li>\n<li>It ensures that the controller classes are found during component scan.<\/li>\n<li>It configures the <em>ExceptionResolver<\/em> bean.<\/li>\n<li>It configures the <em>ViewResolver<\/em> bean.<\/li>\n<\/ol>\n<p>Let\u2019s move on and take a look at the Java configuration class and the XML configuration file.<\/p>\n<h2>Java Configuration<\/h2>\n<p>If we use Java configuration, the source code of the <em>WebAppContext<\/em> class looks as follows:<\/p>\n<pre class=\"brush:java\">import org.springframework.context.annotation.Bean;\r\nimport org.springframework.context.annotation.ComponentScan;\r\nimport org.springframework.context.annotation.Configuration;\r\nimport org.springframework.web.servlet.ViewResolver;\r\nimport org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;\r\nimport org.springframework.web.servlet.config.annotation.EnableWebMvc;\r\nimport org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;\r\nimport org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;\r\nimport org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;\r\nimport org.springframework.web.servlet.view.InternalResourceViewResolver;\r\nimport org.springframework.web.servlet.view.JstlView;\r\n\r\nimport java.util.Properties;\r\n\r\n@Configuration\r\n@EnableWebMvc\r\n@ComponentScan(basePackages = {\r\n        \"net.petrikainulainen.spring.testmvc.common.controller\",\r\n        \"net.petrikainulainen.spring.testmvc.todo.controller\"\r\n})\r\npublic class WebAppContext extends WebMvcConfigurerAdapter {\r\n\r\n    @Override\r\n    public void addResourceHandlers(ResourceHandlerRegistry registry) {\r\n        registry.addResourceHandler(\"\/static\/**\").addResourceLocations(\"\/static\/\");\r\n    }\r\n\r\n    @Override\r\n    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {\r\n        configurer.enable();\r\n    }\r\n\r\n    @Bean\r\n    public SimpleMappingExceptionResolver exceptionResolver() {\r\n        SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver();\r\n\r\n        Properties exceptionMappings = new Properties();\r\n\r\n        exceptionMappings.\r\nput(\"net.petrikainulainen.spring.testmvc.todo.exception.TodoNotFoundException\", \"error\/404\");\r\n        exceptionMappings.put(\"java.lang.Exception\", \"error\/error\");\r\n        exceptionMappings.put(\"java.lang.RuntimeException\", \"error\/error\");\r\n\r\n        exceptionResolver.setExceptionMappings(exceptionMappings);\r\n\r\n        Properties statusCodes = new Properties();\r\n\r\n        statusCodes.put(\"error\/404\", \"404\");\r\n        statusCodes.put(\"error\/error\", \"500\");\r\n\r\n        exceptionResolver.setStatusCodes(statusCodes);\r\n\r\n        return exceptionResolver;\r\n    }\r\n\r\n    @Bean\r\n    public ViewResolver viewResolver() {\r\n        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();\r\n\r\n        viewResolver.setViewClass(JstlView.class);\r\n        viewResolver.setPrefix(\"\/WEB-INF\/jsp\/\");\r\n        viewResolver.setSuffix(\".jsp\");\r\n\r\n        return viewResolver;\r\n    }\r\n}<\/pre>\n<h2>XML Configuration<\/h2>\n<p>If we use XML configuration, the content of the <em>exampleApplicationContext-web.xml<\/em> file looks as follows:<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<pre class=\"brush:xml\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\r\n&lt;beans xmlns=\"http:\/\/www.springframework.org\/schema\/beans\"\r\n      xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"\r\n      xmlns:mvc=\"http:\/\/www.springframework.org\/schema\/mvc\"\r\n      xmlns:context=\"http:\/\/www.springframework.org\/schema\/context\"\r\n      xsi:schemaLocation=\"http:\/\/www.springframework.org\/schema\/beans http:\/\/www.springframework.org\/schema\/beans\/spring-beans.xsd\r\n      http:\/\/www.springframework.org\/schema\/mvc http:\/\/www.springframework.org\/schema\/mvc\/spring-mvc-3.1.xsd\r\n      http:\/\/www.springframework.org\/schema\/context http:\/\/www.springframework.org\/schema\/context\/spring-context-3.1.xsd\"&gt;\r\n\r\n    &lt;mvc:annotation-driven\/&gt;\r\n\r\n    &lt;mvc:resources mapping=\"\/static\/**\" location=\"\/static\/\"\/&gt;\r\n    &lt;mvc:default-servlet-handler\/&gt;\r\n\r\n    &lt;context:component-scan base-package=\"net.petrikainulainen.spring.testmvc.common.controller\"\/&gt;\r\n    &lt;context:component-scan base-package=\"net.petrikainulainen.spring.testmvc.todo.controller\"\/&gt;\r\n\r\n    &lt;bean id=\"exceptionResolver\" class=\"org.springframework.web.servlet.handler.SimpleMappingExceptionResolver\"&gt;\r\n        &lt;property name=\"exceptionMappings\"&gt;\r\n            &lt;props&gt;\r\n                &lt;prop key=\"net.petrikainulainen.spring.testmvc.todo.exception.TodoNotFoundException\"&gt;error\/404&lt;\/prop&gt;\r\n                &lt;prop key=\"java.lang.Exception\"&gt;error\/error&lt;\/prop&gt;\r\n                &lt;prop key=\"java.lang.RuntimeException\"&gt;error\/error&lt;\/prop&gt;\r\n            &lt;\/props&gt;\r\n        &lt;\/property&gt;\r\n        &lt;property name=\"statusCodes\"&gt;\r\n            &lt;props&gt;\r\n                &lt;prop key=\"error\/404\"&gt;404&lt;\/prop&gt;\r\n                &lt;prop key=\"error\/error\"&gt;500&lt;\/prop&gt;\r\n            &lt;\/props&gt;\r\n        &lt;\/property&gt;\r\n    &lt;\/bean&gt;\r\n\r\n    &lt;bean id=\"viewResolver\" class=\"org.springframework.web.servlet.view.InternalResourceViewResolver\"&gt;\r\n        &lt;property name=\"prefix\" value=\"\/WEB-INF\/jsp\/\"\/&gt;\r\n        &lt;property name=\"suffix\" value=\".jsp\"\/&gt;\r\n        &lt;property name=\"viewClass\" value=\"org.springframework.web.servlet.view.JstlView\"\/&gt;\r\n    &lt;\/bean&gt;\r\n&lt;\/beans&gt;<\/pre>\n<h3>Configuring the Test Context<\/h3>\n<p>The configuration of our test context has two responsibilities:<\/p>\n<ol>\n<li>It configures a <em>MessageSource<\/em> bean which is used by our controller class (feedback messages) and Spring MVC (validation error messages). The reason why we need to do this is that the <em>MessageSource<\/em> bean is configured in the \u201cmain\u201d configuration class (or file) of our application context configuration.<\/li>\n<li>It creates a <em>TodoService<\/em> mock which is injected to our controller class.<\/li>\n<\/ol>\n<p>Let\u2019s find out how we configure our test context by using Java configuration class and XML configuration file.<\/p>\n<h2>Java Configuration<\/h2>\n<p>If we configure our test context by using Java configuration, the source code of the <em>TestContext<\/em> class looks as follows:<\/p>\n<pre class=\"brush:java\">import org.mockito.Mockito;\r\nimport org.springframework.context.MessageSource;\r\nimport org.springframework.context.annotation.Bean;\r\nimport org.springframework.context.annotation.Configuration;\r\nimport org.springframework.context.support.ResourceBundleMessageSource;\r\n\r\n@Configuration\r\npublic class TestContext {\r\n\r\n    @Bean\r\n    public MessageSource messageSource() {\r\n        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();\r\n\r\n        messageSource.setBasename(\"i18n\/messages\");\r\n        messageSource.setUseCodeAsDefaultMessage(true);\r\n\r\n        return messageSource;\r\n    }\r\n\r\n    @Bean\r\n    public TodoService todoService() {\r\n        return Mockito.mock(TodoService.class);\r\n    }\r\n}<\/pre>\n<h2>XML Configuration<\/h2>\n<p>If we configure our test context by using an XML configuration, the content of the <em>testContext.xml<\/em> file looks as follow:<\/p>\n<pre class=\"brush:xml\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\r\n&lt;beans xmlns=\"http:\/\/www.springframework.org\/schema\/beans\"\r\n      xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"\r\n      xsi:schemaLocation=\"http:\/\/www.springframework.org\/schema\/beans http:\/\/www.springframework.org\/schema\/beans\/spring-beans.xsd\"&gt;\r\n\r\n    &lt;bean id=\"messageSource\" class=\"org.springframework.context.support.ResourceBundleMessageSource\"&gt;\r\n        &lt;property name=\"basename\" value=\"i18n\/messages\"\/&gt;\r\n        &lt;property name=\"useCodeAsDefaultMessage\" value=\"true\"\/&gt;\r\n    &lt;\/bean&gt;\r\n\r\n    &lt;bean id=\"todoService\" name=\"todoService\" class=\"org.mockito.Mockito\" factory-method=\"mock\"&gt;\r\n        &lt;constructor-arg value=\"net.petrikainulainen.spring.testmvc.todo.service.TodoService\"\/&gt;\r\n    &lt;\/bean&gt;\r\n&lt;\/beans&gt;<\/pre>\n<h2>Configuring The Test Class<\/h2>\n<p>We can configure our test class by using one of the following options:<\/p>\n<ol>\n<li>The Standalone configuration allows us to register one or more controllers (classes annotated with the <em>@Controller<\/em> annotation) and configure the Spring MVC infrastructure programatically. This approach is a viable option if our Spring MVC configuration is simple and straight-forward.<\/li>\n<li>The <em>WebApplicationContext<\/em> based configuration allows us the configure Spring MVC infrastructure by using a fully initialized <em>WebApplicationContext.<\/em> This approach is better if our Spring MVC configuration is so complicated that using standalone configuration does not make any sense.<\/li>\n<\/ol>\n<p>Let\u2019s move on and find out how we can configure our test class by using both configuration options.<\/p>\n<h3>Using Standalone Configuration<\/h3>\n<p>We can configure our test class by following these steps:<\/p>\n<ol>\n<li>Annotate the class with the <em>@RunWith<\/em> annotation and ensure that test is executed by using the <a href=\"http:\/\/docs.mockito.googlecode.com\/hg\/org\/mockito\/runners\/MockitoJUnitRunner.html\" target=\"_blank\"><em>MockitoJUnitRunner<\/em><\/a>.<\/li>\n<li>Add a <a href=\"http:\/\/static.springsource.org\/spring\/docs\/3.2.x\/javadoc-api\/org\/springframework\/test\/web\/servlet\/MockMvc.html\" target=\"_blank\"><em>MockMvc<\/em><\/a> field to the test class.<\/li>\n<li>Add a <em>TodoService<\/em> field to the test class and annotate the field with the <a href=\"http:\/\/docs.mockito.googlecode.com\/hg\/org\/mockito\/Mock.html\" target=\"_blank\"><em>@Mock<\/em><\/a> annotation. This annotation marks the field as a mock. The field is initialized by the <em>MockitoJUnitRunner<\/em>.<\/li>\n<li>Add a private <em>exceptionResolver()<\/em> method to the class. This method creates a new <em>SimpleMappingExceptionResolver<\/em> object, configures it, and returns the created object.<\/li>\n<li>Add a private <em>messageSource()<\/em> method to the class. This method creates a new <em>ResourceBundleMessageSource<\/em> object, configures it, and returns the created object.<\/li>\n<li>Add a private <em>validator()<\/em> method to the class. This method creates a new <em>LocalValidatorFactoryBean<\/em> object and returns the created object.<\/li>\n<li>Add a private <em>viewResolver()<\/em> method to the the class. This method creates a new <em>InternalResourceViewResolver<\/em> object, configures it, and returns the created object.<\/li>\n<li>Add a <em>setUp()<\/em> method to the test class and annotate the method with the <em>@Before<\/em> annotation. This ensures that the method is invoked before each test. This method creates a new <em>MockMvc<\/em> object by calling the <em>standaloneSetup()<\/em> method of the <a href=\"http:\/\/static.springsource.org\/spring\/docs\/3.2.x\/javadoc-api\/org\/springframework\/test\/web\/servlet\/setup\/MockMvcBuilders.html\" target=\"_blank\"><em>MockMvcBuilders<\/em><\/a> class and configures the Spring MVC infrastructure programmatically.<\/li>\n<\/ol>\n<p>The source code of our test class looks as follows:<\/p>\n<pre class=\"brush:java\">import org.junit.Before;\r\nimport org.junit.runner.RunWith;\r\nimport org.mockito.Mock;\r\nimport org.mockito.runners.MockitoJUnitRunner;\r\nimport org.springframework.context.MessageSource;\r\nimport org.springframework.context.support.ResourceBundleMessageSource;\r\nimport org.springframework.test.web.servlet.MockMvc;\r\nimport org.springframework.test.web.servlet.setup.MockMvcBuilders;\r\nimport org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;\r\nimport org.springframework.web.servlet.HandlerExceptionResolver;\r\nimport org.springframework.web.servlet.ViewResolver;\r\nimport org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;\r\nimport org.springframework.web.servlet.view.InternalResourceViewResolver;\r\nimport org.springframework.web.servlet.view.JstlView;\r\n\r\nimport java.util.Properties;\r\n\r\n@RunWith(MockitoJUnitRunner.class)\r\npublic class StandaloneTodoControllerTest {\r\n\r\n    private MockMvc mockMvc;\r\n\r\n    @Mock\r\n    private TodoService todoServiceMock;\r\n\r\n    @Before\r\n    public void setUp() {\r\n        mockMvc = MockMvcBuilders.standaloneSetup(new TodoController(messageSource(), todoServiceMock))\r\n                .setHandlerExceptionResolvers(exceptionResolver())\r\n                .setValidator(validator())\r\n                .setViewResolvers(viewResolver())\r\n                .build();\r\n    }\r\n\r\n    private HandlerExceptionResolver exceptionResolver() {\r\n        SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver();\r\n\r\n        Properties exceptionMappings = new Properties();\r\n\r\n        exceptionMappings.\r\nput(\"net.petrikainulainen.spring.testmvc.todo.exception.TodoNotFoundException\", \"error\/404\");\r\n        exceptionMappings.put(\"java.lang.Exception\", \"error\/error\");\r\n        exceptionMappings.put(\"java.lang.RuntimeException\", \"error\/error\");\r\n\r\n        exceptionResolver.setExceptionMappings(exceptionMappings);\r\n\r\n        Properties statusCodes = new Properties();\r\n\r\n        statusCodes.put(\"error\/404\", \"404\");\r\n        statusCodes.put(\"error\/error\", \"500\");\r\n\r\n        exceptionResolver.setStatusCodes(statusCodes);\r\n\r\n        return exceptionResolver;\r\n    }\r\n\r\n    private MessageSource messageSource() {\r\n        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();\r\n\r\n        messageSource.setBasename(\"i18n\/messages\");\r\n        messageSource.setUseCodeAsDefaultMessage(true);\r\n\r\n        return messageSource;\r\n    }\r\n\r\n    private LocalValidatorFactoryBean validator() {\r\n        return new LocalValidatorFactoryBean();\r\n    }\r\n\r\n    private ViewResolver viewResolver() {\r\n        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();\r\n\r\n        viewResolver.setViewClass(JstlView.class);\r\n        viewResolver.setPrefix(\"\/WEB-INF\/jsp\/\");\r\n        viewResolver.setSuffix(\".jsp\");\r\n\r\n        return viewResolver;\r\n    }\r\n}<\/pre>\n<p>Using the standalone configuration has two problems:<\/p>\n<ol>\n<li>Our test class looks like a mess even though our Spring MVC configuration is rather simple. Naturally, we could clean it up by moving the creation of Spring MVC infrastructure components into a separate class. This is left as an exercise for the reader.<\/li>\n<li>We have to duplicate the configuration of Spring MVC infrastructure components. This means that if we change something in the application context configuration of our application, we must remember to do the same change to our tests as well.<\/li>\n<\/ol>\n<h3>Using WebApplicationContext Based Configuration<\/h3>\n<p>We can configure our test class by following these steps:<\/p>\n<ol>\n<li>Annotate the test class with the <em>@RunWith<\/em> annotation and ensure that the test is executed by using the <em>SpringJUnit4ClassRunner<\/em>.<\/li>\n<li>Annotate the class with the <em>@ContextConfiguration<\/em> annotation and ensure that the correct configuration classes (or XML configuration files) are used. If we want to use Java configuration, we have to set the configuration classes as the value of the <em>classes<\/em> attribute. On the other hand, if we prefer XML configuration, we have to set the configuration files as the value of the <em>locations<\/em> attribute.<\/li>\n<li>Annotate the class with the <em>@WebAppConfiguration<\/em> annotation. This annotation ensures that the application context which is loaded for our test is a <em>WebApplicationContext<\/em>.<\/li>\n<li>Add a <a href=\"http:\/\/static.springsource.org\/spring\/docs\/3.2.x\/javadoc-api\/org\/springframework\/test\/web\/servlet\/MockMvc.html\" target=\"_blank\"><em>MockMvc<\/em><\/a> field to the test class.<\/li>\n<li>Add a <em>TodoService<\/em> field to the test class and annotate the field with the <em>@Autowired<\/em> annotation.<\/li>\n<li>Add a <em>WebApplicationContext<\/em> field to the test class and annotate the field with the <em>@Autowired<\/em> annotation.<\/li>\n<li>Add a <em>setUp()<\/em> method to the test class and annotate the method with the @Before annotation. This ensures that the method is called before each test. This method has responsibilities: it resets the service mock before each test and create a new <em>MockMvc<\/em> object by calling the <em>webAppContextSetup()<\/em> method of the <a href=\"http:\/\/static.springsource.org\/spring\/docs\/3.2.x\/javadoc-api\/org\/springframework\/test\/web\/servlet\/setup\/MockMvcBuilders.html\" target=\"_blank\"><em>MockMvcBuilders<\/em><\/a> class.<\/li>\n<\/ol>\n<p>The source code of our test class looks as follows:<\/p>\n<pre class=\"brush:java\">import org.junit.Before;\r\nimport org.junit.runner.RunWith;\r\nimport org.mockito.Mockito;\r\nimport org.springframework.beans.factory.annotation.Autowired;\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.setup.MockMvcBuilders;\r\nimport org.springframework.web.context.WebApplicationContext;\r\n\r\n@RunWith(SpringJUnit4ClassRunner.class)\r\n@ContextConfiguration(classes = {TestContext.class, WebAppContext.class})\r\n\/\/@ContextConfiguration(locations = {\"classpath:testContext.xml\", \"classpath:exampleApplicationContext-web.xml\"})\r\n@WebAppConfiguration\r\npublic class WebApplicationContextTodoControllerTest {\r\n\r\n    private MockMvc mockMvc;\r\n\r\n    @Autowired\r\n    private TodoService todoServiceMock;\r\n\r\n    @Autowired\r\n    private WebApplicationContext webApplicationContext;\r\n\r\n    @Before\r\n    public void setUp() {\r\n        \/\/We have to reset our mock between tests because the mock objects\r\n        \/\/are managed by the Spring container. If we would not reset them,\r\n        \/\/stubbing and verified behavior would \"leak\" from one test to another.\r\n        Mockito.reset(todoServiceMock);\r\n\r\n        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();\r\n    }\r\n}<\/pre>\n<p>The configuration of our test class looks a lot cleaner than the configuration which uses standalone configuration. However, the \u201cdownside\u201d is that our test uses the full Spring MVC infrastructure. This might be an overkill if our test class really uses only a few components.<\/p>\n<h2>Summary<\/h2>\n<p>We have now configured our unit test class by using both the standalone setup and the <em>WebApplicationContext<\/em> based setup. This blog post has taught us two things:<\/p>\n<ul>\n<li>We learned that it is important to divide the application context configuration in a such way that we can reuse parts of it in our tests.<\/li>\n<li>We learned the difference between the standalone configuration and the <em>WebApplicationContext<\/em> based configuration.<\/li>\n<\/ul>\n<p>The next part of this tutorial describes how we can write unit tests for \u201cnormal\u201d Spring MVC controllers.<\/p>\n<p>P.S. The example application of this blog post is available at <a href=\"https:\/\/github.com\/pkainulainen\/spring-mvc-test-examples\/tree\/master\/controllers-unittest\" target=\"_blank\">Github<\/a>.<br \/>\n&nbsp;<\/p>\n<div style=\"border: 1px solid #D8D8D8; background: #FAFAFA; width: 100%; padding-left: 5px;\"><b><i>Reference: <\/i><\/b><a href=\"http:\/\/www.petrikainulainen.net\/programming\/spring-framework\/unit-testing-of-spring-mvc-controllers-configuration\/\">Unit Testing of Spring MVC Controllers: Configuration<\/a> from our <a href=\"http:\/\/www.javacodegeeks.com\/jcg\">JCG partner<\/a> Petri Kainulainen at the <a href=\"http:\/\/www.petrikainulainen.net\/\">Petri Kainulainen<\/a> blog.<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Writing unit tests for Spring MVC controllers has traditionally been both simple and problematic. Although it is pretty simple to write unit tests which invoke controller methods, the problem is that those unit tests are not comprehensive enough. For example, we cannot test controller mappings, validation and exception handling just by invoking the tested controller &hellip;<\/p>\n","protected":false},"author":429,"featured_media":240,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[30,150],"class_list":["post-15087","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-enterprise-java","tag-spring","tag-spring-mvc"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Unit Testing of Spring MVC Controllers: Configuration<\/title>\n<meta name=\"description\" content=\"Writing unit tests for Spring MVC controllers has traditionally been both simple and problematic. Although it is pretty simple to write unit tests which\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/2013\/07\/unit-testing-of-spring-mvc-controllers-configuration-2.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Unit Testing of Spring MVC Controllers: Configuration\" \/>\n<meta property=\"og:description\" content=\"Writing unit tests for Spring MVC controllers has traditionally been both simple and problematic. Although it is pretty simple to write unit tests which\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2013\/07\/unit-testing-of-spring-mvc-controllers-configuration-2.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2013-07-04T22:00:03+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Petri Kainulainen\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/petrikainulaine\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Petri Kainulainen\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"13 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/unit-testing-of-spring-mvc-controllers-configuration-2.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/unit-testing-of-spring-mvc-controllers-configuration-2.html\"},\"author\":{\"name\":\"Petri Kainulainen\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/5af4df3fdfeb79e9fa3598d79bff2c9e\"},\"headline\":\"Unit Testing of Spring MVC Controllers: Configuration\",\"datePublished\":\"2013-07-04T22:00:03+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/unit-testing-of-spring-mvc-controllers-configuration-2.html\"},\"wordCount\":1573,\"commentCount\":1,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/unit-testing-of-spring-mvc-controllers-configuration-2.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"keywords\":[\"Spring\",\"Spring MVC\"],\"articleSection\":[\"Enterprise Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/unit-testing-of-spring-mvc-controllers-configuration-2.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/unit-testing-of-spring-mvc-controllers-configuration-2.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/unit-testing-of-spring-mvc-controllers-configuration-2.html\",\"name\":\"Unit Testing of Spring MVC Controllers: Configuration\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/unit-testing-of-spring-mvc-controllers-configuration-2.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/unit-testing-of-spring-mvc-controllers-configuration-2.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"datePublished\":\"2013-07-04T22:00:03+00:00\",\"description\":\"Writing unit tests for Spring MVC controllers has traditionally been both simple and problematic. Although it is pretty simple to write unit tests which\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/unit-testing-of-spring-mvc-controllers-configuration-2.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/unit-testing-of-spring-mvc-controllers-configuration-2.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/unit-testing-of-spring-mvc-controllers-configuration-2.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"width\":150,\"height\":150,\"caption\":\"spring-interview-questions-answers\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/unit-testing-of-spring-mvc-controllers-configuration-2.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Enterprise Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/enterprise-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Unit Testing of Spring MVC Controllers: Configuration\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/5af4df3fdfeb79e9fa3598d79bff2c9e\",\"name\":\"Petri Kainulainen\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/9e57425180f323fa65bc519a64c8273d3fcb7c6bd272e56b37dd15613f403659?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/9e57425180f323fa65bc519a64c8273d3fcb7c6bd272e56b37dd15613f403659?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/9e57425180f323fa65bc519a64c8273d3fcb7c6bd272e56b37dd15613f403659?s=96&d=mm&r=g\",\"caption\":\"Petri Kainulainen\"},\"description\":\"Petri is passionate about software development and continuous improvement. He is specialized in software development with the Spring Framework and is the author of Spring Data book.\",\"sameAs\":[\"http:\\\/\\\/www.petrikainulainen.net\\\/\",\"http:\\\/\\\/www.linkedin.com\\\/in\\\/petrikainulainen\",\"https:\\\/\\\/x.com\\\/https:\\\/\\\/twitter.com\\\/petrikainulaine\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/petri-kainulainen\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Unit Testing of Spring MVC Controllers: Configuration","description":"Writing unit tests for Spring MVC controllers has traditionally been both simple and problematic. Although it is pretty simple to write unit tests which","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/2013\/07\/unit-testing-of-spring-mvc-controllers-configuration-2.html","og_locale":"en_US","og_type":"article","og_title":"Unit Testing of Spring MVC Controllers: Configuration","og_description":"Writing unit tests for Spring MVC controllers has traditionally been both simple and problematic. Although it is pretty simple to write unit tests which","og_url":"https:\/\/www.javacodegeeks.com\/2013\/07\/unit-testing-of-spring-mvc-controllers-configuration-2.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2013-07-04T22:00:03+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","type":"image\/jpeg"}],"author":"Petri Kainulainen","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/petrikainulaine","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Petri Kainulainen","Est. reading time":"13 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2013\/07\/unit-testing-of-spring-mvc-controllers-configuration-2.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/07\/unit-testing-of-spring-mvc-controllers-configuration-2.html"},"author":{"name":"Petri Kainulainen","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/5af4df3fdfeb79e9fa3598d79bff2c9e"},"headline":"Unit Testing of Spring MVC Controllers: Configuration","datePublished":"2013-07-04T22:00:03+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/07\/unit-testing-of-spring-mvc-controllers-configuration-2.html"},"wordCount":1573,"commentCount":1,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/07\/unit-testing-of-spring-mvc-controllers-configuration-2.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","keywords":["Spring","Spring MVC"],"articleSection":["Enterprise Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2013\/07\/unit-testing-of-spring-mvc-controllers-configuration-2.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2013\/07\/unit-testing-of-spring-mvc-controllers-configuration-2.html","url":"https:\/\/www.javacodegeeks.com\/2013\/07\/unit-testing-of-spring-mvc-controllers-configuration-2.html","name":"Unit Testing of Spring MVC Controllers: Configuration","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/07\/unit-testing-of-spring-mvc-controllers-configuration-2.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/07\/unit-testing-of-spring-mvc-controllers-configuration-2.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","datePublished":"2013-07-04T22:00:03+00:00","description":"Writing unit tests for Spring MVC controllers has traditionally been both simple and problematic. Although it is pretty simple to write unit tests which","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/07\/unit-testing-of-spring-mvc-controllers-configuration-2.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2013\/07\/unit-testing-of-spring-mvc-controllers-configuration-2.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2013\/07\/unit-testing-of-spring-mvc-controllers-configuration-2.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","width":150,"height":150,"caption":"spring-interview-questions-answers"},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/2013\/07\/unit-testing-of-spring-mvc-controllers-configuration-2.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Enterprise Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/enterprise-java"},{"@type":"ListItem","position":4,"name":"Unit Testing of Spring MVC Controllers: Configuration"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/5af4df3fdfeb79e9fa3598d79bff2c9e","name":"Petri Kainulainen","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/9e57425180f323fa65bc519a64c8273d3fcb7c6bd272e56b37dd15613f403659?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/9e57425180f323fa65bc519a64c8273d3fcb7c6bd272e56b37dd15613f403659?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/9e57425180f323fa65bc519a64c8273d3fcb7c6bd272e56b37dd15613f403659?s=96&d=mm&r=g","caption":"Petri Kainulainen"},"description":"Petri is passionate about software development and continuous improvement. He is specialized in software development with the Spring Framework and is the author of Spring Data book.","sameAs":["http:\/\/www.petrikainulainen.net\/","http:\/\/www.linkedin.com\/in\/petrikainulainen","https:\/\/x.com\/https:\/\/twitter.com\/petrikainulaine"],"url":"https:\/\/www.javacodegeeks.com\/author\/petri-kainulainen"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/15087","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/429"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=15087"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/15087\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/240"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=15087"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=15087"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=15087"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}