javascript
Spring MVC控制器的单元测试:配置
傳統上,為Spring MVC控制器編寫單元測試既簡單又成問題。 盡管編寫調用控制器方法的單元測試非常簡單,但問題是這些單元測試不夠全面。 例如,我們不能僅通過調用已測試的控制器方法來測試控制器映射,驗證和異常處理。
Spring MVC Test通過使我們能夠通過DispatcherServlet調用控制器方法來解決了這個問題。 這是本教程的第一部分,描述了Spring MVC控制器的單元測試,并描述了如何配置單元測試。 讓我們開始吧。
使用Maven獲取所需的依賴關系
我們可以通過在pom.xml文件中聲明以下測試依賴項來獲取所需的依賴項:
- JUnit 4.11
 - Mockito Core 1.9.5
 - Spring測試3.2.3發布
 
pom.xml文件的相關部分如下所示:
<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version><scope>test</scope> </dependency> <dependency><groupId>org.mockito</groupId><artifactId>mockito-core</artifactId><version>1.9.5</version><scope>test</scope> </dependency> <dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>3.2.3.RELEASE</version><scope>test</scope> </dependency>讓我們繼續前進,快速看一下示例應用程序。
我們的示例應用程序剖析
本教程的示例應用程序為待辦事項提供CRUD操作。 為了了解測試類的配置,我們必須對測試的控制器類有一些了解。
在這一點上,我們需要知道以下問題的答案:
- 它有什么依賴性?
 - 如何實例化?
 
通過查看TodoController類的源代碼,我們可以獲得這些問題的答案。 TodoController類的相關部分如下所示:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.MessageSource; import org.springframework.stereotype.Controller;@Controller public class TodoController {private final TodoService service;private final MessageSource messageSource;@Autowiredpublic TodoController(MessageSource messageSource, TodoService service) {this.messageSource = messageSource;this.service = service;}//Other methods are omitted. }如我們所見,控制器類具有兩個依賴項: TodoService和MessageSource 。 另外,我們可以看到我們的控制器類使用構造函數注入。
至此,這就是我們需要的所有信息。 接下來,我們將討論我們的應用程序上下文配置。
配置應用程序上下文
為我們的應用程序和測試維護單獨的應用程序上下文配置很麻煩。 同樣,如果我們在應用程序的應用程序上下文配置中進行了某些更改,但是忘記對測試上下文進行相同的更改,則會導致問題。
這就是為什么對示例應用程序的應用程序上下文配置進行劃分的原因,我們可以在測試中重用部分應用程序。
我們的應用程序上下文配置劃分如下:
- 第一個應用程序配置類稱為ExampleApplicationContext ,它是我們應用程序的“主要”配置類。
 - 第二個配置類負責配置應用程序的Web層。 此類的名稱是WebAppContext ,它是我們在測試中將使用的配置類。
 - 第三個配置類稱為PersistenceContext ,它包含應用程序的持久性配置。
 
注意:示例應用程序還具有使用XML配置文件的有效應用程序上下文配置。 與Java配置類相對應的XML配置文件為: exampleApplicationContext.xml ,exampleApplicationContext-web.xml和exampleApplicationContext-persistence.xml 。
讓我們看一下Web層的應用程序上下文配置,并了解如何配置測試上下文。
配置Web層
Web層的應用程序上下文配置具有以下職責:
讓我們繼續看一下Java配置類和XML配置文件。
Java配置
如果使用Java配置,則WebAppContext類的源代碼如下所示:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver; import org.springframework.web.servlet.view.InternalResourceViewResolver; import org.springframework.web.servlet.view.JstlView;import java.util.Properties;@Configuration @EnableWebMvc @ComponentScan(basePackages = {"net.petrikainulainen.spring.testmvc.common.controller","net.petrikainulainen.spring.testmvc.todo.controller" }) public class WebAppContext extends WebMvcConfigurerAdapter {@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {registry.addResourceHandler("/static/**").addResourceLocations("/static/");}@Overridepublic void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {configurer.enable();}@Beanpublic SimpleMappingExceptionResolver exceptionResolver() {SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver();Properties exceptionMappings = new Properties();exceptionMappings. put("net.petrikainulainen.spring.testmvc.todo.exception.TodoNotFoundException", "error/404");exceptionMappings.put("java.lang.Exception", "error/error");exceptionMappings.put("java.lang.RuntimeException", "error/error");exceptionResolver.setExceptionMappings(exceptionMappings);Properties statusCodes = new Properties();statusCodes.put("error/404", "404");statusCodes.put("error/error", "500");exceptionResolver.setStatusCodes(statusCodes);return exceptionResolver;}@Beanpublic ViewResolver viewResolver() {InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();viewResolver.setViewClass(JstlView.class);viewResolver.setPrefix("/WEB-INF/jsp/");viewResolver.setSuffix(".jsp");return viewResolver;} }XML配置
如果使用XML配置, exampleApplicationContext-web.xml文件的內容如下所示:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"><mvc:annotation-driven/><mvc:resources mapping="/static/**" location="/static/"/><mvc:default-servlet-handler/><context:component-scan base-package="net.petrikainulainen.spring.testmvc.common.controller"/><context:component-scan base-package="net.petrikainulainen.spring.testmvc.todo.controller"/><bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"><property name="exceptionMappings"><props><prop key="net.petrikainulainen.spring.testmvc.todo.exception.TodoNotFoundException">error/404</prop><prop key="java.lang.Exception">error/error</prop><prop key="java.lang.RuntimeException">error/error</prop></props></property><property name="statusCodes"><props><prop key="error/404">404</prop><prop key="error/error">500</prop></props></property></bean><bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/jsp/"/><property name="suffix" value=".jsp"/><property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/></bean> </beans>配置測試上下文
我們的測試上下文的配置有兩個職責:
讓我們了解如何使用Java配置類和XML配置文件配置測試上下文。
Java配置
如果我們通過使用Java配置來配置測試上下文,則TestContext類的源代碼如下所示:
import org.mockito.Mockito; import org.springframework.context.MessageSource; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.support.ResourceBundleMessageSource;@Configuration public class TestContext {@Beanpublic MessageSource messageSource() {ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();messageSource.setBasename("i18n/messages");messageSource.setUseCodeAsDefaultMessage(true);return messageSource;}@Beanpublic TodoService todoService() {return Mockito.mock(TodoService.class);} }XML配置
如果我們使用XML配置來配置測試上下文,那么testContext.xml文件的內容如下所示:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"><property name="basename" value="i18n/messages"/><property name="useCodeAsDefaultMessage" value="true"/></bean><bean id="todoService" name="todoService" class="org.mockito.Mockito" factory-method="mock"><constructor-arg value="net.petrikainulainen.spring.testmvc.todo.service.TodoService"/></bean> </beans>配置測試類別
我們可以使用以下選項之一配置測試類:
讓我們繼續前進,找出如何使用這兩個配置選項來配置測試類。
使用獨立配置
我們可以按照以下步驟配置測試類:
我們的測試類的源代碼如下所示:
import org.junit.Before; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; import org.springframework.context.MessageSource; import org.springframework.context.support.ResourceBundleMessageSource; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver; import org.springframework.web.servlet.view.InternalResourceViewResolver; import org.springframework.web.servlet.view.JstlView;import java.util.Properties;@RunWith(MockitoJUnitRunner.class) public class StandaloneTodoControllerTest {private MockMvc mockMvc;@Mockprivate TodoService todoServiceMock;@Beforepublic void setUp() {mockMvc = MockMvcBuilders.standaloneSetup(new TodoController(messageSource(), todoServiceMock)).setHandlerExceptionResolvers(exceptionResolver()).setValidator(validator()).setViewResolvers(viewResolver()).build();}private HandlerExceptionResolver exceptionResolver() {SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver();Properties exceptionMappings = new Properties();exceptionMappings. put("net.petrikainulainen.spring.testmvc.todo.exception.TodoNotFoundException", "error/404");exceptionMappings.put("java.lang.Exception", "error/error");exceptionMappings.put("java.lang.RuntimeException", "error/error");exceptionResolver.setExceptionMappings(exceptionMappings);Properties statusCodes = new Properties();statusCodes.put("error/404", "404");statusCodes.put("error/error", "500");exceptionResolver.setStatusCodes(statusCodes);return exceptionResolver;}private MessageSource messageSource() {ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();messageSource.setBasename("i18n/messages");messageSource.setUseCodeAsDefaultMessage(true);return messageSource;}private LocalValidatorFactoryBean validator() {return new LocalValidatorFactoryBean();}private ViewResolver viewResolver() {InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();viewResolver.setViewClass(JstlView.class);viewResolver.setPrefix("/WEB-INF/jsp/");viewResolver.setSuffix(".jsp");return viewResolver;} }使用獨立配置有兩個問題:
使用基于WebApplicationContext的配置
我們可以按照以下步驟配置測試類:
我們的測試類的源代碼如下所示:
import org.junit.Before; import org.junit.runner.RunWith; import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; 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.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext;@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = {TestContext.class, WebAppContext.class}) //@ContextConfiguration(locations = {"classpath:testContext.xml", "classpath:exampleApplicationContext-web.xml"}) @WebAppConfiguration public class WebApplicationContextTodoControllerTest {private MockMvc mockMvc;@Autowiredprivate TodoService todoServiceMock;@Autowiredprivate WebApplicationContext webApplicationContext;@Beforepublic void setUp() {//We have to reset our mock between tests because the mock objects//are managed by the Spring container. If we would not reset them,//stubbing and verified behavior would "leak" from one test to another.Mockito.reset(todoServiceMock);mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();} }我們的測試類的配置看起來比使用獨立配置的配置干凈得多。 但是,“缺點”是我們的測試使用了完整的Spring MVC基礎架構。 如果我們的測試類僅實際使用一些組件,則這可能是過大的殺傷力。
摘要
現在,我們已經使用獨立安裝程序和基于WebApplicationContext的安裝程序配置了單元測試類。 這篇博客文章教會了我們兩件事:
- 我們了解到,劃分應用程序上下文配置很重要,這樣我們才能在測試中重用部分內容。
 - 我們了解了獨立配置和基于WebApplicationContext的配置之間的區別。
 
本教程的下一部分描述了如何為“常規” Spring MVC控制器編寫單元測試。
 PS此博客文章的示例應用程序可在Github上獲得 。 
翻譯自: https://www.javacodegeeks.com/2013/07/unit-testing-of-spring-mvc-controllers-configuration-2.html
總結
以上是生活随笔為你收集整理的Spring MVC控制器的单元测试:配置的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: 安卓fifa15离线版(安卓fifa15
 - 下一篇: Spring MVC测试框架入门–第2部