用于测试的 spring junit 加载应用程序上下文
Posted
技术标签:
【中文标题】用于测试的 spring junit 加载应用程序上下文【英文标题】:spring junit load application context for tests 【发布时间】:2013-02-03 11:22:08 【问题描述】:我的 WEB-INF 目录下有一些 XML 文件:
lyricsBaseApp-servlet.xml hibernate.xml dataSource.xml beans.xmlservlet xml 导入其他 xml 文件:
<import resource="dataSource.xml"/>
<import resource="hibernate.xml"/>
<import resource="beans.xml"/>
我希望我的 junit4 JukeboxTest
类包含整个弹簧配置。使用默认文件名我创建了一个JukeboxTest-content.xml
文件。最后,我不知道该放什么...
我试过了:
<import resource="/WEB-INF/dataSource.xml"/>
<import resource="/WEB-INF/hibernate.xml"/>
<import resource="/WEB-INF/beans.xml"/>
或
<import resource="classpath:./WEB-INF/dataSource.xml"/>
<import resource="classpath:./WEB-INF/hibernate.xml"/>
<import resource="classpath:./WEB-INF/beans.xml"/>
还有一些其他的想法,但都失败了。有人可以指出我如何访问这些文件以及 spring 以什么方式解释这些文件路径?
【问题讨论】:
【参考方案1】:选项 1(应该首选,因为它是最佳做法):
在WEB-INF
下重构您的配置文件,并将公共部分(您也希望从集成测试中访问)移动到src/main/resources/
。然后在src/test/resources/
中编写测试专用配置文件(如果你只需要从src/main
导入几个不同的配置文件来组装你的测试上下文,那么跳过这个,最好使用@ContextConfiguration
)。
选项 2(破解): 使用如下引用:
@ContextConfiguration("file:src/main/webapp/WEB-INF/dataSource.xml")
选项 3(破解):
如果您有一个 Maven 项目,您可以配置 maven-surefire-plugin
(在测试阶段使用)以在测试执行期间将 src/main/webapp
声明为附加的类路径元素。
后两个选项被认为是 hack,因为src/main/webapp
下的文件根本不应该在类路径上。
现在详细解释:
您不能将这些文件称为classpath:/WEB-INF/*.xml
的原因是它们确实不在类路径中。了解您的 web 应用程序是如何打包的,以及类路径中的最终结果是什么,这一点很重要。假设一个默认的 Maven 项目结构:
-
来自
src/main/java
的Java 类在编译后转到/WEB-INF/classes
。
src/main/resources
的资源也转到/WEB-INF/classes
。
项目依赖转到/WEB-INF/lib
。
src/main/webapp
中的所有内容都转到/
(包的根目录)。这意味着来自src/main/webapp/WEB-INF
的所有文件当然会转到/WEB-INF
。
要知道的最重要的事情是类路径将只包含/WEB-INF/classes
和/WEB-INF/lib
中每个jar 的一个条目。因此,这两个位置之外的资源对于类加载器来说是完全不可见的。这对于 直接位于 /WEB-INF
下的 xml 配置文件也是如此,这就是为什么引用 classpath:/WEB-INF/dataSource.xml
永远不会起作用的原因。
您可能会问自己,如果这些 xml 配置文件无法从类路径访问,那么这些 xml 配置文件是如何被 Spring 加载的呢?答案很简单:当你启动你的 web 应用程序(而不是只执行单元/集成测试)时,它运行在一个 Servlet 容器中,它提供对ServletContext
(来自 Servlet API 的一个实际类)的访问,所以它使用ServletContext.getResourceAsStream()
加载这些文件。理解的关键是下面这个方法的javadoc的引用:
此方法与使用类加载器的 java.lang.Class.getResourceAsStream 不同。此方法允许 servlet 容器从任何位置为 servlet 提供资源,而无需使用类加载器。
对不起,这太长了,但这就是整个故事......
【讨论】:
如何引用src/test/resources中的上下文文件? @Kris 的答案是唯一对我有用的答案。 选择选项 1 .. 然后您如何实际加载该上下文文件? @zagyi 如何将 src/main/webapp 声明为测试上下文中的附加类路径之一?【参考方案2】:试试这个
@ContextConfiguration(locations = "classpath:**/dataSource.xml",
"classpath:**/hibernate.xml",
"classpath:**/WEB-INF/beans.xml")
【讨论】:
这对我来说适用于 src/test/resources 中的 application-context.xml。以上是关于用于测试的 spring junit 加载应用程序上下文的主要内容,如果未能解决你的问题,请参考以下文章
Spring4 JUnit 测试:将 SQL 加载到 H2 数据库
JUnit 4 & Spring Boot - 在测试前有选择地重新加载上下文/重新加载 Spring Security 配置
Spring Hibernate H2 Junit 测试 - 如何在启动时加载模式
java.lang.IllegalStateException:无法加载 ApplicationContext Spring Boot + JUnit 测试