![](/img/trans.png)
[英]PowerMockito mocking static testing controller in spring 3.2.4
[英]Alternative to testing controllers in Spring 3.2.4
在Spring 3.0.5及之前的版本中,可以創建一個基本控制器測試類,該類從Spring Application Context中獲取HandlerMapping對象,以通過URL直接訪問並調用控制器的方法。 我發現這種方法確實很棒,因為除了測試控制器的方法外,我還在單元/集成測試中測試了路徑變量等。
在Spring 3.2.4中,由於重新構造了Spring處理Url映射的方式,這種方法似乎不再可行。 我看到Spring提供了一個新的MVC測試框架,但老實說,我認為它的設計過於冗長,看上去與框架的其余部分或我的應用程序代碼完全不同。 它也無法與IntelliJ中的智能感知功能配合使用。 老實說,我寧願不使用它。
那么,有沒有像我以前那樣不使用新的Spring MVC測試框架來測試控制器URL的替代方法? 我有一個具有371個控制器測試的現有項目,並且我真的很想避免遷移所有內容以使用Spring MVC測試框架。
這是我使用Spring 3.0.5來測試控制器的handle()
方法:
protected ModelAndView handle(HttpServletRequest request, HttpServletResponse response) throws Exception {
final HandlerMapping handlerMapping = applicationContext.getBean(HandlerMapping.class);
final HandlerExecutionChain handler = handlerMapping.getHandler(request);
assertNotNull("No handler found for request, check you request mapping", handler);
final Object controller = handler.getHandler();
final HandlerInterceptor[] interceptors = handlerMapping.getHandler(request).getInterceptors();
for (HandlerInterceptor interceptor : interceptors) {
final boolean carryOn = interceptor.preHandle(request, response, controller);
if (!carryOn) {
return null;
}
}
return handlerAdapter.handle(request, response, controller);
}
protected ModelAndView handle(String method, String path, String queryString) throws Exception {
request.setMethod(method);
request.setRequestURI(path);
if(queryString != null) {
String[] parameters = queryString.split("&");
for(String parameter : parameters) {
String[] pair = parameter.split("=");
if(pair.length == 2) {
request.setParameter(pair[0], pair[1]);
} else {
request.setParameter(pair[0], "");
}
}
}
return handle(request, response);
}
protected ModelAndView handle(String method, String path, String attribute, Object object) throws Exception {
MockHttpSession session = new MockHttpSession();
session.setAttribute(attribute, object);
request.setSession(session);
return handle(method, path, null);
}
protected ModelAndView handle(String method, String path) throws Exception {
return handle(method, path, null);
}
這是一些測試代碼,說明我如何使用handle()
方法:
@Test
public void show() throws Exception {
ModelAndView modelAndView = handle("GET", "/courseVersion/1/section/1");
Section section = (Section) modelAndView.getModel().get("section");
assertEquals(1, section.getId());
}
這是我的servlet應用程序上下文:
<?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"
xmlns:security="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations" value="classpath:applicationContext.properties"/>
</bean>
<bean id="expressionHandler"
class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
</bean>
<security:global-method-security pre-post-annotations="enabled">
<security:expression-handler ref="expressionHandler"/>
</security:global-method-security>
<context:component-scan base-package="keiko.web.controllers"/>
<mvc:annotation-driven validator="validator" />
<mvc:interceptors>
<bean class="keiko.web.interceptors.IpValidationInterceptor" />
<bean class="keiko.web.interceptors.UnreadMessagesInterceptor" />
<bean class="keiko.web.interceptors.ThemeInterceptor" />
<bean class="keiko.web.interceptors.ApplicationMenuInterceptor" />
</mvc:interceptors>
<bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/freemarker/"/>
<property name="freemarkerSettings">
<props>
<prop key="auto_import">lib/common.ftl as common, lib/layouts.ftl as layouts</prop>
<prop key="whitespace_stripping">true</prop>
</props>
</property>
<property name="freemarkerVariables">
<map>
<entry key="template_update_delay" value="0"/>
<entry key="default_encoding" value="ISO-8859-1"/>
<entry key="number_format" value="0.##"/>
<entry key="xml_escape">
<bean class="freemarker.template.utility.XmlEscape"/>
</entry>
</map>
</property>
</bean>
<bean id="contentNegotiatingViewResolver"
class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="order" value="1"/>
<property name="ignoreAcceptHeader" value="true" />
<property name="defaultContentType" value="text/html" />
<property name="mediaTypes">
<map>
<entry key="html" value="text/html"/>
<entry key="json" value="application/json"/>
</map>
</property>
<property name="useNotAcceptableStatusCode" value="true" />
<property name="viewResolvers">
<list>
<bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="contentType" value="text/html" />
<property name="order" value="2"/>
<property name="cache" value="${freemarker.cache}"/>
<property name="prefix" value=""/>
<property name="suffix" value=".ftl"/>
<property name="exposeSpringMacroHelpers" value="true"/>
</bean>
</list>
</property>
<property name="defaultViews">
<list>
<bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
<property name="contentType" value="application/json" />
</bean>
</list>
</property>
</bean>
<bean id="viewNameTranslator" class="org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator"/>
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="1000000"/>
</bean>
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="keiko.domain.courseauthor.SectionIsDelayedException">error/sectionIsDelayed</prop>
<prop key="keiko.service.director.CompanyHomepageClosedException">error/registrationClosed</prop>
<prop key="keiko.service.director.IpDeniedException">error/ipDenied</prop>
</props>
</property>
</bean>
</beans>
基本上,您的測試方法從一開始就存在缺陷。 總是有可能存在1個HandlerMapping
和1個HandlerAdapter。 您基本上在做什么是模仿DispatcherServlet。
您應該做的是查找所有HandlerMapping
和HandlerAdapter
並檢查它們中是否有一個與URL匹配(即返回HandlerExecutionChain),然后選擇適當的HandlerAdapter
(調用supports
方法)。 您要做的基本上就是DispatcherServlet
所做的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.