我正在尝试交换应用程序上下文文件,这样我就可以在我的IDE中使用真实的测试或在我的IDE中使用带有测试的JUnit进行测试。
一个简单的例子是:
mainConfig.xml
<context:component-scan base-package="myPackage" />
<bean id="myBean" class="my.class"/>
testConfig.xml
<context:component-scan base-package="myPackage" />
<bean id="myBean" class="my.test.class"/>
我处理应用程序Context的java代码与下面类似(但实际上是单例)
public final class MyLoader {
private ApplicationContext context;
public MyLoader(){
context = new ClassPathXmlApplicationContext(
"classpath:/hardcoded/path/to/mainConfig.xml");
}
public <T> T getComponent(final Class<T> type) {
return (T) context.getBean(type);
}
}
MyLoader是从代码中的多个点调用的,因为应用程序有许多不同的入口点。
我的JUnit测试代码
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:/hardcoded/path/to/testConfig.xml")
public final class Foo{}
当我运行JUnit测试时,它将加载testConfig.xml(由于JUnit文件中的@ContextConfiguration),但它也将加载mainConfig.xml(因为ClassPathXmlApplication)。这会导致冲突,因为这两个文件不同。
如果不发生这样的不匹配,将所有这些连线的正确方法是什么?
答案 0 :(得分:1)
考虑到加载spring上下文和访问bean的方式,你似乎有一个特定的场景。
类路径优先。
将main.xml
和test.xml
个文件放在不同的目录中,但两者使用相同的名称(例如main/config.xml
和test/config.xml
)。然后配置IDE,以便在运行jUnit
时,测试目录优先于类路径中的主目录。
这实际上是maven
默认获得的内容。在这种情况下,您可能需要通过使用IDE来自己烹饪。
环境变量。
另一个选项是用于配置config.xml
位置的环境变量,然后在MyLoader
中使用该值,可能默认为main.xml
以避免在正常执行中进行额外配置。
public MyLoader(){
context = new ClassPathXmlApplicationContext(
System.getProperty("config.location", "classpath:path/to/mainConfig.xml"));
然后,您可以配置IDE以在运行jUnit时设置该环境变量,或者从相应地设置变量的基类扩展测试:
System.setProperty("config.location", "classpath:/path/to/testConfig.xml")
这里你真的不需要SpringJUnit4ClassRunner,因为通过使用MyLoader你无论如何都懒惰地加载了上下文。
这些不是很好的解决方案。
删除MyLoader
,不要使用单例来保留spring上下文和/或检索bean。
在应用程序的入口点初始化ClassPathXmlApplicationContext
,然后在获取第一个bean之后,您不再需要ApplicationContext
。
对组件之间的依赖关系使用正确的自动装配/注入。而不是从MyLoader
检索它们。
假设它是非Web应用程序,Web应用程序使用ContextLoaderListener
加载config xml。
遵循此方法后,在使用SpringJUnit4ClassRunner
加载不同的config.xml时不应该遇到任何问题,因为在运行测试时您没有从入口点运行应用程序。
每次需要弹簧组件时,您都不会MyLoader
尝试延迟加载主上下文。
答案 1 :(得分:-1)
你应该真正研究使用Maven和JavaConfig。使用XML文件是2000风格,你需要更新你的风格来制作时间。看看JavaConfig和Maven,这很容易做到。