如何做网站app,辅助网站建设,做渔家乐哪个网站最好,购房网站系统建设方案传统上#xff0c;为Spring MVC控制器编写单元测试既简单又成问题。 尽管编写调用控制器方法的单元测试非常简单#xff0c;但问题是这些单元测试不够全面。 例如#xff0c;我们不能仅通过调用已测试的控制器方法来测试控制器映射#xff0c;验证和异常处理。 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文件的相关部分如下所示 dependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion4.11/versionscopetest/scope
/dependency
dependencygroupIdorg.mockito/groupIdartifactIdmockito-core/artifactIdversion1.9.5/versionscopetest/scope
/dependency
dependencygroupIdorg.springframework/groupIdartifactIdspring-test/artifactIdversion3.2.3.RELEASE/versionscopetest/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层的应用程序上下文配置具有以下职责 它启用了注释驱动的Spring MVC。 它配置静态资源例如CSS文件和Javascript文件的位置。 它确保静态资源由容器的默认Servlet提供。 它确保在组件扫描期间找到控制器类。 它配置ExceptionResolver bean。 它配置ViewResolver bean。 让我们继续看一下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 version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:mvchttp://www.springframework.org/schema/mvcxmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://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.xsdmvc:annotation-driven/mvc:resources mapping/static/** location/static//mvc:default-servlet-handler/context:component-scan base-packagenet.petrikainulainen.spring.testmvc.common.controller/context:component-scan base-packagenet.petrikainulainen.spring.testmvc.todo.controller/bean idexceptionResolver classorg.springframework.web.servlet.handler.SimpleMappingExceptionResolverproperty nameexceptionMappingspropsprop keynet.petrikainulainen.spring.testmvc.todo.exception.TodoNotFoundExceptionerror/404/propprop keyjava.lang.Exceptionerror/error/propprop keyjava.lang.RuntimeExceptionerror/error/prop/props/propertyproperty namestatusCodespropsprop keyerror/404404/propprop keyerror/error500/prop/props/property/beanbean idviewResolver classorg.springframework.web.servlet.view.InternalResourceViewResolverproperty nameprefix value/WEB-INF/jsp//property namesuffix value.jsp/property nameviewClass valueorg.springframework.web.servlet.view.JstlView//bean
/beans配置测试上下文 我们的测试上下文的配置有两个职责 它配置一个MessageSource bean供我们的控制器类反馈消息和Spring MVC验证错误消息使用。 我们之所以需要这样做是因为MessageSource bean是在应用程序上下文配置的“主”配置类或文件中配置的。 它创建一个TodoService模拟该模拟被注入到我们的控制器类中。 让我们了解如何使用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 version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdbean idmessageSource classorg.springframework.context.support.ResourceBundleMessageSourceproperty namebasename valuei18n/messages/property nameuseCodeAsDefaultMessage valuetrue//beanbean idtodoService nametodoService classorg.mockito.Mockito factory-methodmockconstructor-arg valuenet.petrikainulainen.spring.testmvc.todo.service.TodoService//bean
/beans配置测试类别 我们可以使用以下选项之一配置测试类 Standalone配置允许我们注册一个或多个控制器使用Controller注释注释的类并以编程方式配置Spring MVC基础结构。 如果我们的Spring MVC配置简单明了那么这种方法是可行的选择。 基于WebApplicationContext的配置允许我们使用完全初始化的WebApplicationContext来配置Spring MVC基础结构。 如果我们的Spring MVC配置太复杂以至于使用独立配置没有任何意义那么这种方法会更好。 让我们继续前进找出如何使用这两个配置选项来配置测试类。 使用独立配置 我们可以按照以下步骤配置测试类 使用RunWith注释为类添加注释并确保使用MockitoJUnitRunner执行测试。 将MockMvc字段添加到测试类。 将TodoService字段添加到测试类并使用Mock注释对字段进行注释。 此注释将字段标记为模拟。 该字段由MockitoJUnitRunner初始化。 向该类添加一个私有的exceptionResolver方法。 此方法创建一个新的SimpleMappingExceptionResolver对象对其进行配置然后返回创建的对象。 将私有messageSource方法添加到该类。 此方法创建一个新的ResourceBundleMessageSource对象对其进行配置然后返回创建的对象。 向该类添加一个私有的validator方法。 此方法创建一个新的LocalValidatorFactoryBean对象并返回创建的对象。 向该类添加一个专用的viewResolver方法。 此方法创建一个新的InternalResourceViewResolver对象对其进行配置然后返回创建的对象。 将setUp方法添加到测试类并使用Before注释对方法进行注释。 这样可以确保在每次测试之前都调用该方法。 该方法通过调用MockMvcBuilders类的standaloneSetup方法创建一个新的MockMvc对象并以编程方式配置Spring MVC基础结构。 我们的测试类的源代码如下所示 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;}
} 使用独立配置有两个问题 即使我们的Spring MVC配置非常简单我们的测试类看起来还是一团糟。 当然我们可以通过将Spring MVC基础结构组件的创建移到一个单独的类中来清理它。 这留给读者练习。 我们必须复制Spring MVC基础结构组件的配置。 这意味着如果我们更改应用程序的应用程序上下文配置中的某些内容则必须记住也要对测试进行相同的更改。 使用基于WebApplicationContext的配置 我们可以按照以下步骤配置测试类 使用RunWith注释对测试类进行注释并确保通过使用SpringJUnit4ClassRunner执行测试。 用ContextConfiguration注释为该类添加注释并确保使用正确的配置类或XML配置文件。 如果要使用Java配置则必须将配置类设置为classes属性的值。 另一方面如果我们更喜欢XML配置则必须将配置文件设置为locations属性的值。 用WebAppConfiguration批注对类进行批注。 此批注确保为我们的测试加载的应用程序上下文是WebApplicationContext 。 将MockMvc字段添加到测试类。 将TodoService字段添加到测试类并使用Autowired批注对该字段进行批注。 将WebApplicationContext字段添加到测试类并使用Autowired批注对该字段进行批注。 将setUp方法添加到测试类并使用Before注释对方法进行注释。 这样可以确保在每次测试之前都调用该方法。 此方法负责在每次测试之前重置服务模拟并通过调用MockMvcBuilders类的webAppContextSetup方法来创建新的MockMvc对象。 我们的测试类的源代码如下所示 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上获得 。 参考 Spring MVC控制器的单元测试 Petri Kainulainen博客上来自我们JCG合作伙伴 Petri Kainulainen的配置 。 翻译自: https://www.javacodegeeks.com/2013/07/unit-testing-of-spring-mvc-controllers-configuration-2.html