【问题标题】:Spring MockMVC for a programmatically created WebApplicationContext用于以编程方式创建的 WebApplicationContext 的 Spring MockMVC
【发布时间】:2014-06-28 02:28:45
【问题描述】:

我想使用 springs MockMVC 工具编写集成测试:

MockMvcBuilders.webAppContextSetup(...).build();

阅读可用的文档http://docs.spring.io/spring/docs/current/spring-framework-reference/html/testing.html#spring-mvc-test-framework 留下一个问题:如何为以编程方式创建的 WebApplicationContext 设置测试?

如果我正确理解了模拟 mvc 测试的概念,它会神奇地发现一个 servlet 上下文,其中包含调度程序 servlet 和一个用于设置的 WebApplicationContext。目前,我手动创建 WebApplicationContext 并将 DispatcherServlet 添加到码头实例。我想我必须以某种方式将其解耦?

我想使用 SpringWebConfiguration.class 中定义的 web 上下文并模拟 SpringConfiguration.class 中定义的根上下文中的所有内容

public static void main(String[] args) throws Exception {
    SimpleCommandLinePropertySource ps = new SimpleCommandLinePropertySource(args);

    ApplicationContext rootContext = createRootContext(ps);

    //start jetty
    Server server = new Server(Integer.parseInt(ps.getProperty("port")));
    ServletContextHandler contextHandler = new ServletContextHandler();
    contextHandler.setContextPath("/");
    createWebContext(rootContext, contextHandler);
    server.setHandler(contextHandler);

    server.start();
    server.join();
}

private static ApplicationContext createRootContext(PropertySource propertySource) {
    AnnotationConfigApplicationContext rootContext = new AnnotationConfigApplicationContext();
    rootContext.getEnvironment().getPropertySources().addFirst(propertySource);
    rootContext.register(SpringConfiguration.class); //main configuration class for all beans
    rootContext.refresh();
    return rootContext;
}


public static WebApplicationContext createWebContext(ApplicationContext rootContext) {
    AnnotationConfigWebApplicationContext webApplicationContext = new AnnotationConfigWebApplicationContext();
    webApplicationContext.setParent(rootContext);
    webApplicationContext.register(SpringWebConfiguration.class);
    return webApplicationContext;
}

private static WebApplicationContext createWebContext(ApplicationContext rootContext, ServletContextHandler servletContext) throws ServletException {
    WebApplicationContext webApplicationContext = createWebContext(rootContext);

    /* enable logging of each http request */
    servletContext.addFilter(LoggingFilterChain.class, "/*", EnumSet.of(DispatcherType.REQUEST));
    registerDispatcherServlet("api", servletContext, webApplicationContext);
    return webApplicationContext;
}

private static DispatcherServlet registerDispatcherServlet(String path, ServletContextHandler servletContext, WebApplicationContext ctx) {
    DispatcherServlet servlet = new DispatcherServlet(ctx);
    servletContext.addServlet(new ServletHolder(servlet), "/" + path + "/*");
    return servlet;
}

知道我必须如何更改配置才能使用 mockmvc 测试吗?我更喜欢没有 spring.xml / web.xml 的解决方案。

【问题讨论】:

    标签: spring spring-mvc servlets junit spring-mvc-test


    【解决方案1】:

    遗憾的是没有答案,但过了一段时间我了解了 Spring 开发人员的意图以及 servlet 上下文是如何工作的:

    在问题中,我使用 jetty 来启动具有特定上下文的特定 DispatcherServlet。没有魔法,很清楚会发生什么。没有办法在两者之间嘲笑一些东西。为了将 servlet 容器(码头)与实际的 Web 应用程序上下文分开,我必须:

    1. 使用 springs WebApplicationInitializer 接口并在那里配置上下文

    2. 让码头找到上下文。这部分有点棘手,因为我的 jetty 版本只扫描 jar 文件,所以我决定最好将我的 jetty 与我的 Web 应用程序强耦合:

    --

    WebAppContext webAppContext = new WebAppContext();
    webAppContext.setConfigurations(new Configuration[]{new ConcreteConfiguration(ServletInitializer.class)}); //that class implements the WebApplicationInitializer of spring.
    
    //...
    
    /**
     * Configures a concrete WebApplicationInitializer
     */
    static class ConcreteConfiguration extends AnnotationConfiguration {
    
        private final Class<?> initializerClass;
    
        ConcreteConfiguration(Class<?> initializerClass) {
            this.initializerClass = initializerClass;
        }
    
        @Override
        public void preConfigure(WebAppContext context) throws Exception {
            MultiMap<String> map = new MultiMap<String>();
            map.add(WebApplicationInitializer.class.getName(), initializerClass.getName());
            context.setAttribute(CLASS_INHERITANCE_MAP, map);
            _classInheritanceHandler = new ClassInheritanceHandler(map);
        }
    }
    

    (我在这里找到了静态内部类的想法:https://stackoverflow.com/a/15702616/320299

    【讨论】:

      猜你喜欢
      • 2013-10-03
      • 2023-03-12
      • 1970-01-01
      • 1970-01-01
      • 2011-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-02
      相关资源
      最近更新 更多