Announcement Announcement Module
Collapse
No announcement yet.
Testing controller + Freemarker view outside web container Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Testing controller + Freemarker view outside web container

    I'm trying to test my controller plus view resolution plus freemarker processes outside of a web container. (maybe this is just crazy).

    I have code such as:

    Code:
    MockHttpServletRequest request = new MockHttpServletRequest("POST", "/doStuff.html");
    MockHttpServletResponse response = new MockHttpServletResponse();
    DoStuffController controller = (DoStuffController) applicationContext.getBean("DoStuffController");
    
    ModelAndView mav = controller.handleRequest(request, response);
    Configuration cfg = (Configuration) applicationContext.getBean("freemarkerConfig");
    
    Template template = cfg.getTemplate("doStuff.ftl");
    StringWriter out = new StringWriter();
    template.process(mav.getModel(), out);
    
    //assert expected results.
    In my ftl file I'm using the form input generation macros. My problem is the springMacroRequestContext is undefined within the spring.ftl. Is there a way to mock this? Or set it from within my test?

    Thanks.

  • #2
    Code:
    ModelAndView mav = controller.handleRequest(request, response);
    You're close. You want to get the view associated with it like so (put this code in an abstract junit test case that you've extended so that other tests can use it):
    Code:
     public View getViewFromMv(ModelAndView mv) throws Exception {
            if (mv.getView() != null)
                return mv.getView();
            assertNotNull(mv.getViewName());
            return getViewResolver().resolveViewName(mv.getViewName(),
                    defaultLocale);
        }
     public ViewResolver getViewResolver() {
            return (ViewResolver) ctx.getBean("viewResolver");
        }
    Then you can do the following with your code:
    Code:
    ModelAndView mav = controller.handleRequest(request, response);
    getViewFromMv(mav).render(mav.getModel(), request, response);
    System.out.println(response.getContentAsString();
    You could use the String output of getContentAsString() and then parse through it to see if it the correct response.

    Comment


    • #3
      Thanks. But now I'm running into this problem.

      Code:
      java.lang.IllegalStateException: No WebApplicationContext found: not in a DispatcherServlet request?
      	at org.springframework.web.servlet.support.RequestContextUtils.getWebApplicationContext(RequestContextUtils.java:78)
      	at org.springframework.web.servlet.support.RequestContext.initContext(RequestContext.java:203)
      	at org.springframework.web.servlet.support.RequestContext.<init>&#40;RequestContext.java&#58;155&#41;
      	at org.springframework.web.servlet.view.AbstractTemplateView.renderMergedOutputModel&#40;AbstractTemplateView.java&#58;157&#41;
      	at org.springframework.web.servlet.view.AbstractView.render&#40;AbstractView.java&#58;250&#41;
      Here I'm *trying* to setup up the XMLWebApplicationContext:
      Code:
      protected void setUp&#40;&#41; throws Exception &#123;
              String&#91;&#93; contexts = getConfigLocations&#40;&#41;;
              webCtx = new XmlWebApplicationContext&#40;&#41;;
              webCtx.setConfigLocations&#40;contexts&#41;;
              webCtx.setServletContext&#40;new MockServletContext&#40;""&#41;&#41;;
      
              webCtx.refresh&#40;&#41;;
          &#125;
      Any ideas? Thanks.

      Comment


      • #4
        Code:
        public MockHttpServletRequest getRequest&#40;&#41; &#123;
                MockHttpServletRequest req = new MockHttpServletRequest&#40;ctx
                        .getServletContext&#40;&#41;&#41;;
                req.setMethod&#40;"GET"&#41;;
                req.setAttribute&#40;DispatcherServlet.LOCALE_RESOLVER_ATTRIBUTE, ctx
                        .getBean&#40;"localeResolver"&#41;&#41;;
                req.setAttribute&#40;DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE,
                        ctx&#41;;
                assertEquals&#40;"en", req.getLocale&#40;&#41;.getLanguage&#40;&#41;&#41;;
                return req;
            &#125;

        Comment


        • #5
          Works! Great.

          Thanks for your help. Much appreciated.

          Comment


          • #6
            Hi guys,

            I am trying to achieve the same with Spring 3.0 + Freemarker 2.3.16. I have AbstractControllerTestSupport which is setting up the configuration as specified in this post but when I run my controller integration test the view is not resolved.

            View view = getViewFromMv(mav);

            view is NULL here.

            Here is my freemarker view resolver config:

            HTML Code:
            <!-- freemarker config -->
            	<bean id="freemarkerConfig"
            		class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer" >
            		<property name="templateLoaderPath" value="/WEB-INF/views/freemarker/" />
            	</bean>
            
            
            	<bean id="viewResolver"
            		class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
            		<property name="cache" value="true" />
            		<property name="prefix" value="" />
            		<property name="suffix" value=".ftl" />
            	</bean>
            Here is my AbstractControllerTestSupport code:

            Code:
            public abstract class AbstractControllerTestSupport {
                private XmlWebApplicationContext webContext;
            
                private MockServletContext ctx;
            
                @Before
                public void setUp() {
                    ctx = new MockServletContext(new FileSystemResourceLoader());
                    String[] contexts = new String[] { "classpath:x-webapp-servlet.xml" };
                    webContext = new XmlWebApplicationContext();
                    webContext.setConfigLocations(contexts);
                    webContext.setServletContext(ctx);
                    webContext.refresh();
            
                }
            
                public ModelAndView handle(HttpServletRequest request, HttpServletResponse response) throws Exception {
                    final HandlerAdapter handlerAdapter = webContext.getBean(AnnotationMethodHandlerAdapter.class);
                    final HandlerMapping handlerMapping = webContext.getBean(DefaultAnnotationHandlerMapping.class);
                    final HandlerExecutionChain handler = handlerMapping.getHandler(request);
                    Assert.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;
                        }
                    }
                    final ModelAndView mav = handlerAdapter.handle(request, response, controller);
                    return mav;
                }
            
                public MockHttpServletResponse mockResponse() {
                    return new MockHttpServletResponse();
                }
            
                public MockHttpServletRequest mockRequest(String method, String uri, Map<String, String> params) {
                    MockHttpServletRequest req = new MockHttpServletRequest(webContext.getServletContext(), method, uri);
                    if (params != null) {
                        for (String key : params.keySet()) {
                            req.addParameter(key, params.get(key));
                        }
                    }
            
                    req.setAttribute(DispatcherServlet.LOCALE_RESOLVER_ATTRIBUTE, webContext.getBean("localeResolver"));
                    req.setAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE, webContext);
                    return req;
                }
            
                public View getViewFromMv(ModelAndView mv) throws Exception {
                    if (mv.getView() != null) {
                        return mv.getView();
                    }
                    Assert.assertNotNull(mv.getViewName());
                    return getViewResolver().resolveViewName(mv.getViewName(), Locale.getDefault());
                }
            
                public ViewResolver getViewResolver() {
                    return (ViewResolver) webContext.getBean("viewResolver");
                }
            
            }
            The application works fine in web container.

            Thanks for your help in advance.

            Comment

            Working...
            X