Spring -Test-MVC / MockServletContext - content is empty in the test, but works on Tomcat

We are trying to configure Spring-Test-MVC for our Spring-MVC web application. We started using freemarker and everything was fine. We decided against this, although now we are trying to configure it using JSP. When the test application is deployed to Tomcat, it works. When we run a simple test:

@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!"))); } 

he says: content type not set , or if this is deleted, the content will be empty. However, the controller will be called, so the display should work.

So, this strongly suggests that the view is not displayed for our tests, but I don’t know which installation I could skip.

Here is our 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 is the original Spring -test-mvc.

MockMvc gets the installation as a Bean as follows:

 @Configuration public class TestConfig { @Inject private WebApplicationContext wac; @Bean public MockMvc create(){ return (MockMvcBuilders.webApplicationContextSetup(this.wac).build()); } } 

So, to set up. web.xml is not used by the testing platform and does not matter since it worked before.

I think that in the servlet context there should be an additional configuration. It loads, I checked, but so far for the deployed Tomcat application it is important that I set it for the prefix and suffix, it will simply be ignored by the test.

Not sure how error tracing will help, but here it is:

 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) 

And test output:

 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 

So thanks for any suggestions that will help me find the problem!

Btw: I didn't want this to get bigger, so I skipped pom. We are using Spring 3.1, Spring -test-mvc 1.0.0..BUILD-SNAPSHOT, jsp-ap 2.2, jstl 1.2, ... If you need to know more, I will try to download it somewhere ...


Edit

Please let me know if you need more information or why you cannot answer my question. Actually, you need to figure this out, and I have no idea where to start. Therefore, any thoughts or comments are also welcome.


Edit2

The printing method is used with the following output:

 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 = [] 

Which only shows the problem better, but not the solution ...


Edit3

The following has just been revealed:

JSP requires a servlet container. So it seems that I cannot check my pages this way ... If anyone knows how to get around this problem, please let me know ..

+8
java spring-mvc servlets testing mocking
source share
3 answers

Adding to your edit3, mainly for JSP rendering, the final call

 RequestDispatcher requestDispatcher = httpRequest.getRequestDispacher(jspPath) requestDispatcher.forward(httpRequest,httpResponse) 

and RequestDispatcher implementations RequestDispatcher provided by the container (since it depends on how you want to compile jsp, where to put the compiled jsp, etc.). The breadcrumb implementation of RequestDispatcher simply captures the redirected JSP page, and you can only confirm that the path to the JSP is what you expect.

+1
source share

@Biju - I appreciate this answer, and it saved me on the trip, and I'm not going to take the messenger here, but I have to say that in any case, the Spring team, which may be motivated to build something better, I find MockMVC to be significant degrees of exercise in triviality and futility. First, Spring authentication is not directly supported. Well, if you say StackOverflow, you can find a workaround to this. Then on my own I found that if you use the Spring context configuration, every path you can make is returned as “OK”, even if it should return “notFound”. Well, whatever it takes, pull it out and let's not talk about it anymore. :) And now find out that MockMVC is really MockMC - viewing processing does not occur. Thus, in the end, what is this software suitable for, is testing applications that contain neither security nor representations - what would be, in fact, JSON application toys?

And this is actually not the answer, this is rant, which means that now MockMVC will cost me the reputation of StackOverflow! :) The hulk crashed!

[EDIT] - Okay, aside, there seem to be ways around this. [LATER EDIT] Unfortunately, the path around this that I found is no longer available.

+8
source share

I created a modified version of MockRequestDispatcher that builds the same chain as MockMvc and passes the request to this chain for forward queries. This fixes this problem for me. Another work must be done if the view is displayed outside the dispatcher servlet (for example, via jsp).

Code is: https://gist.github.com/micw/a8b20720db900762a29d

Most of the work was to bring it to the right place. I did this by creating a RequestPostProcessor for MockMvc and some layout magic that intercepts the call to MockHttpServletRequest.getRequestDispatcher.

To use it, add it to your test path and call it immediately after creating the MockMvc instance:

  mvc = MockMvcBuilders.webAppContextSetup(webApplicationContext) [...] .build(); WebMvcRequestDispatcherForwardFix.apply(mvc); 
0
source share

All Articles