[英]Spring-Test-MVC / MockServletContext - content empty in test but working on Tomcat
我們正在嘗試為Spring-MVC Web應用程序設置Spring-Test-MVC。 我們開始使用freemarker,一切都很好。 我們決定反對它,現在正試圖用JSP進行設置。 當測試應用程序部署在Tomcat上時,它正在運行。 當我們運行簡單測試時:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = WebContextLoader.class, locations = { "file:src/main/webapp/WEB-INF/servlet-context.xml" })
public class SkelletonTest {
@Inject
private MockMvc mockMvc;
@Test
public void homeTest() throws Exception {
mockMvc.perform(get("/")).andExpect(status().isOk())
.andExpect(content().type("text/html;charset=ISO-8859-1"))
.andExpect(content().string(containsString("Hello World!")));
}
它說: content type not set
或如果刪除,內容將為空。 然而,控制器將被調用,因此映射必須起作用。
所以這強烈暗示我們的測試沒有呈現視圖,但我不知道我可能缺少什么設置。
這是我們的servlet-context.xml:
<context:component-scan base-package="package.to.controllers" />
<mvc:annotation-driven />
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="exposeContextBeansAsAttributes" value="true" />
<property name="prefix" value="/views/" />
<property name="suffix" value=".jsp" />
</bean>
WebContextLoader:
public class WebContextLoader extends GenericWebContextLoader {
public WebContextLoader() {
super("src/main/webapp", false);
}
}
GenericWebContextLoader是spring-test-mvc的原始版本。
MockMvc像這樣設置為Bean:
@Configuration
public class TestConfig {
@Inject
private WebApplicationContext wac;
@Bean
public MockMvc create(){
return (MockMvcBuilders.webApplicationContextSetup(this.wac).build());
}
}
這就是設置。 測試框架不使用web.xml,因為它之前的工作並不重要。
我想在servlet-context中必須有一個額外的設置。 它被加載了,我檢查了但是對於Tomcat部署的應用程序而言重要的是,我為前綴和后綴設置它將被測試忽略。
不確定錯誤跟蹤有多大幫助,但這里是:
java.lang.AssertionError: Content type not set
at org.springframework.test.web.AssertionErrors.fail(AssertionErrors.java:35)
at org.springframework.test.web.AssertionErrors.assertTrue(AssertionErrors.java:57)
at org.springframework.test.web.server.result.ContentResultMatchers$1.match(ContentResultMatchers.java:59)
at org.springframework.test.web.server.MockMvc$1.andExpect(MockMvc.java:84)
at our.package.SkelletonTest.homeTest(SkelletonTest.java:30)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
並測試輸出:
2012-06-15 10:41:04 TestContextManager [INFO] @TestExecutionListeners is not present for class [class package.to.test.SkelletonTest]: using defaults.
2012-06-15 10:41:05 XmlBeanDefinitionReader [INFO] Loading XML bean definitions from URL [file:src/main/webapp/WEB-INF/servlet-context.xml]
2012-06-15 10:41:05 ClassPathBeanDefinitionScanner [INFO] JSR-330 'javax.inject.Named' annotation found and supported for component scanning
2012-06-15 10:41:05 GenericWebApplicationContext [INFO] Refreshing org.springframework.web.context.support.GenericWebApplicationContext@158539f: startup date [Fri Jun 15 10:41:05 CEST 2012]; root of context hierarchy
2012-06-15 10:41:05 AutowiredAnnotationBeanPostProcessor [INFO] JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
2012-06-15 10:41:05 DefaultListableBeanFactory [INFO] Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@c64bc2: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,testConfig,freemarkerController,homeController,tableService,org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#0,org.springframework.format.support.FormattingConversionServiceFactoryBean#0,org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#0,org.springframework.web.servlet.handler.MappedInterceptor#0,org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver#0,org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver#0,org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver#0,org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,viewResolver,org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor#0,create]; root of factory hierarchy
2012-06-15 10:41:05 RequestMappingHandlerMapping [INFO] Mapped "{[/],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public org.springframework.web.servlet.ModelAndView package.to.controller.HomeController.index()
2012-06-15 10:41:05 RequestMappingHandlerMapping [INFO] Mapped "{[/test],methods=[],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.lang.String package.to.controller.HomeController.test(org.springframework.ui.Model)
2012-06-15 10:41:06 GenericWebContextLoader$1 [INFO] Initializing Spring FrameworkServlet ''
2012-06-15 10:41:06 TestDispatcherServlet [INFO] FrameworkServlet '': initialization started
2012-06-15 10:41:06 TestDispatcherServlet [INFO] FrameworkServlet '': initialization completed in 32 ms
2012-06-15 10:41:06 GenericWebApplicationContext [INFO] Closing org.springframework.web.context.support.GenericWebApplicationContext@158539f: startup date [Fri Jun 15 10:41:05 CEST 2012]; root of context hierarchy
2012-06-15 10:41:06 DefaultListableBeanFactory [INFO] Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@c64bc2: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,testConfig,freemarkerController,homeController,tableService,org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#0,org.springframework.format.support.FormattingConversionServiceFactoryBean#0,org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#0,org.springframework.web.servlet.handler.MappedInterceptor#0,org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver#0,org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver#0,org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver#0,org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,viewResolver,org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor#0,create]; root of factory hierarchy
所以感謝任何有助於我找到問題的建議!
順便說一句:不想再這樣了,所以我跳過了pom。 我們正在使用Spring 3.1,spring-test-mvc 1.0.0..BUILD-SNAPSHOT,jsp-ap 2.2,jstl 1.2,...如果您需要了解更多,我會嘗試將其上傳到某個地方......
編輯
如果您需要更多信息或為什么無法回答我的問題,請告訴我。 真的需要搞清楚,我不知道,從哪里開始。 所以也歡迎任何想法或評論。
EDIT2
使用具有以下輸出的print方法:
MockHttpServletRequest:
HTTP Method = GET
Request URI = /
Parameters = {}
Headers = {}
Handler:
Type = package.to.controller.HomeController
Method = public org.springframework.web.servlet.ModelAndView package.to.controller.HomeController.index()
Resolved Exception:
Type = null
ModelAndView:
View name = index
View = null
Attribute = welcome
value = Hello World!
FlashMap:
MockHttpServletResponse:
Status = 200
Error message = null
Headers = {}
Content type = null
Body =
Forwarded URL = /views/index.jsp
Redirected URL = null
Cookies = []
這只是更好地展示問題而不是解決方案......
EDIT3
剛發現以下內容:
JSP需要一個servlet容器。 所以我似乎無法以這種方式測試我的頁面...如果有人知道如何解決這個問題,請讓我知道..
@Biju - 我很欣賞這個答案,它讓我省去了一次旅行,而且我不是想在這里拍攝信使,但我必須說出春天團隊中任何一個可能有動力去建立更好的東西的人的利益,我我發現MockMVC幾乎是一種瑣碎無用的練習。 首先,不直接支持Spring身份驗證。 如果你偵察StackOverflow,你可以找到一個解決方法。 然后我自己發現,如果你有彈簧上下文配置,你可以彌補的每個路徑都會返回“OK”,即使它應該返回“notFound”。 好吧,無論如何,把它拿出去讓我們再也不說了。 :)現在來發現MockMVC實際上只是MockMC - 沒有視圖處理發生。 因此,在一天結束時,這個軟件最適合的是測試既不包含安全性也不包含視圖的應用程序 - 這將是什么,確切地說,玩具JSON應用程序是什么?
這不是一個真正的答案,這是一個咆哮,這意味着現在MockMVC將花費我StackOverflow的聲譽! :) 綠巨人粉碎!
[編輯] - 好吧咆哮它看起來確實有這樣的方法。 [LATER EDIT]不幸的是我找到的方式不再可用了。
添加到您的edit3,主要是為JSP呈現最終調用
RequestDispatcher requestDispatcher = httpRequest.getRequestDispacher(jspPath)
requestDispatcher.forward(httpRequest,httpResponse)
並且RequestDispatcher
實現由容器提供(因為它取決於如何編譯jsp,在何處放置已編譯的jsp等)。 RequestDispatcher的Mock實現只是捕獲轉發的JSP頁面,您只能驗證JSP的路徑是否符合您的預期。
我創建了一個MockRequestDispatcher的修改版本,它與MockMvc構建相同的鏈,並將請求傳遞給該鏈以用於轉發請求。 這為我解決了這個問題。 如果視圖在調度程序servlet之外呈現(例如通過jsp),則必須完成更多工作。
代碼在那里: https : //gist.github.com/micw/a8b20720db900762a29d
大多數工作是在正確的地方注入它。 我這樣做了我為MockMvc創建一個RequestPostProcessor和一些攔截MockHttpServletRequest.getRequestDispatcher調用的mockito-magic。
要使用它,請將其添加到測試類路徑並在創建MockMvc實例后直接調用它:
mvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
[...]
.build();
WebMvcRequestDispatcherForwardFix.apply(mvc);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.