【问题标题】:Write Junit tests for Spring MVC application which internally relies upon ContextLoader.getCurrentWebApplicationContext()为内部依赖 ContextLoader.getCurrentWebApplicationContext() 的 Spring MVC 应用程序编写 Junit 测试
【发布时间】:2012-05-13 13:44:40
【问题描述】:

我正在尝试为我们的 spring mvc 应用程序中的控制器编写集成测试。控制器调用一个服务类,该服务类又调用一个 dao 从存储库中读取/写入数据。 DAO 需要查找一些配置。配置 bean 定义在 WEB-INF/applicationContext.xml 中。

我正在使用这样的东西:

配置 config =(Configuration)ContextLoader.getCurrentWebApplicationContext().getBean("config");
私有字符串命名空间 = config.getProperty("someproperty");

属性存储在zookeeper中,所以我没有使用spring的属性管理工件。

问题是在运行 JUnit 测试时 ContextLoader.getCurrentWebApplicationContext() 总是返回 null。

到目前为止,我已经研究了以下方法:
1. Ted Young的做法(随便google搜索spring mvc集成测试ted young)
2.https://github.com/SpringSource/spring-test-mvc
3. 这个网站.. questions/8464919/unit-testing-a-servlet-that-depends-on-springs-webapplicationcontextutils-getre
4. 使用 Selenium/JWebunit
5.http://confluence.highsource.org/display/Hifaces20/Hifaces20+Testing+package+-+testing%2C+tracing+and+debugging+web+applications+with+Jetty

1 无法解决此问题。 WebApplicationContext 保持为空
2 声明将在 Spring 3.2 中提供对 WebApplicationContext 的支持
3. 我不明白这个。我从哪里获得 testApplicationContext 和 getServletContext()?
4. 我不想走这条路,因为这完全是黑盒测试。
5. 我目前正在看 5. 但这需要启动一个 servlet 容器。没有其他选择吗?

如果您能提供任何帮助,我将不胜感激。

谢谢 PixalSoft

@Ted Young SO 不允许我完成我所说的话。使用 loader=MockWebApplicationContextLoader,它不应该可以作为默认上下文加载器使用,就像 Spring ContextLoader 在 webapp 由 servletcontainer 初始化时的行为一样?有什么特别的事情需要我来处理 MockWebApplicationContextLoader 吗?注入配置对象适用于单例对象。但不可能都是单例的。在每个构造函数中传递一个配置对象听起来太乏味了。现在,我创建了一个具有静态配置对象的类,通过 setter 方法自动装配。我会看看 ApplicationContextAware.Many thx

【问题讨论】:

    标签: spring-mvc


    【解决方案1】:

    您必须手动将 WebApplication 上下文添加到 ContextLoderListner。 这将起作用。

    @ContextConfiguration(locations = "classpath:module-test-beans.xml")
    @WebAppConfiguration
    public class SampleTest extends AbstractTestNGSpringContextTests {
    
        @Autowired
        private WebApplicationContext wac;
    
        @BeforeClass
        public void setUp() throws ServletException {
            MockServletContext sc = new MockServletContext("");
            ServletContextListener listener = new ContextLoaderListener(wac);
            ServletContextEvent event = new ServletContextEvent(sc);
            listener.contextInitialized(event);
        }
    
        @Test
        public void testMe() {
            Assert.assertFalse(ContextLoader.getCurrentWebApplicationContext() == null);
        }
    }
    

    【讨论】:

      【解决方案2】:

      在 junit 测试的开头添加以下代码:

      MockServletContext sc = new MockServletContext("");
      sc.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM,
              "/applicationContext-test.xml"); // <== Customize with your paths
      ServletContextListener listener = new ContextLoaderListener();
      ServletContextEvent event = new ServletContextEvent(sc);
      listener.contextInitialized(event);
      

      如果您需要为上下文路径添加多个 xml,只需将它们放在以空格分隔的同一字符串中,如下所示:

      sc.addInitParameter(ContextLoader.CONFIG_LOCATION_PARAM,
              "/applicationContext-test.xml /applicationContext-other.xml");
      

      【讨论】:

      【解决方案3】:

      ContextLoader.getCurrentWebApplicationContext 返回 null 的原因是,当您使用我的 MockWebApplicationContextLoader 时,您既没有使用 Web 应用程序上下文,也没有使用特定的 ContextLoader 实现。

      既然你的存储库是由 Spring 管理的,为什么不简单地将配置对象注入到存储库中呢?注入配置对象是访问它的最合适的方式。然后,您可以在使用 @PostConstruct 注释的方法中初始化您的命名空间属性。

      或者,您的 DOA 可以实现 ApplicationContextAware 以在构建期间接收应用程序上下文的副本。

      【讨论】:

      • 嗨,如果我使用 loader=MockWebApplicationContextLoader,它不应该可以作为默认上下文加载器使用,就像 Spring 上下文加载器在 web 应用程序由 servlet 容器初始化时的行为一样吗?我需要做些什么特别的事情来处理 MockWebApplicationContextLoader 吗? OTOH,如果它的行为不是这样,我为什么需要它?
      • 不,它假定不可用。您必须扩展 MWACL 来配置 ContextLoader,我看不出有什么简单的方法可以做到这一点。由于这种原因,使用 ContextLoader 是一个坏主意。您确实应该首先问自己为什么要使用 ContextLoader 来访问 ApplicationContext。
      • 我们使用 ContextLoader 是因为根本不可能在需要的地方注入 spring bean。 AFAIK ContextLoader.getCWAC() 是 API 的有效用法。谢谢。
      【解决方案4】:

      将您的属性文件存储在您的类路径中。

      现在像这样在你的控制器类中访问该属性:

      /*to access your filename.properties file */
      properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("filename.properties"));
      
      String  sServerLocation = properties.getProperty("key");
      

      现在您可以访问您的属性文件了。

      我相信它会起作用的。

      【讨论】:

      • 您好,感谢您的回复。我们无法将属性存储在属性文件中,因为我们处于分布式环境中,因此我们需要将属性存储在 zookeeper 中。另外,我不认为使用 ContextLoader.getCurrentWebApplicationContext() 应该会阻止应用程序进行单元测试。
      猜你喜欢
      • 2021-05-17
      • 1970-01-01
      • 2016-04-30
      • 1970-01-01
      • 2012-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-02
      相关资源
      最近更新 更多