我在resources.xml
文件夹下有grailsApp/conf/spring
并且所有bean都已初始化,但我希望测试Vs的实际上有不同的bean定义。
我是否可以单独test-resources.xml
并在测试期间加载它,而在加载resources.xml
时会加载它?
答案 0 :(得分:2)
您是否仅限于使用XML进行bean定义?使用resources.groovy
是首选方法,因为它提供了强大的DSL,根据环境定义bean很简单:
import grails.util.Environment
beans = {
switch(Environment.current) {
case Environment.TEST:
myBean(String, "test string")
break
case Environment.DEVELOPMENT:
myBean(String, "dev string")
break
}
}
您可以在Grails and Spring上的文档中查看更多示例。
如果您无法使用Grails Spring DSL进行bean定义,则可以使用某种混合方法。将resources.xml移出conf/spring/
以及类路径上的其他位置。在它旁边,创建另一个XML文件,该文件包含测试环境的bean定义,我们称之为resources-test.xml
。然后使用以下内容将resources.groovy文件添加到conf/spring/
:
import grails.util.Environment
beans = {
switch(Environment.current) {
case Environment.TEST:
importBeans('classpath:/resources-test.xml')
break
case Environment.DEVELOPMENT:
importBeans('classpath:/resources.xml')
break
}
}
此方法允许您将bean定义保留为XML,但使用Grails Spring DSL来打开环境。
根据您在resources.xml中处理的bean的复杂性和数量,也许您可以使用BeanFactoryPostProcessor
。 Spring的BeanFactoryPostProcessor允许您在初始化之前挂钩bean,以便您可以修改它们的定义。您需要在src/groovy
中创建一个实现BeanFactoryPostProcessor
的类,如下所示:
import grails.util.Environment
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory
import org.springframework.beans.BeansException
import org.springframework.beans.factory.config.ConstructorArgumentValues
class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
if (Environment.current == Environment.TEST) {
BeanDefinition definition = beanFactory.getBeanDefinition('myBean')
ConstructorArgumentValues constructorArgs = definition.constructorArgumentValues
constructorArgs.clear()
constructorArgs.addGenericArgumentValue("Modified for test")
}
}
}
然后在resources.xml中注册:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="myBean" class="java.lang.String">
<constructor-arg value="this will be overwritten" />
</bean>
<bean id="postProcessor" class="CustomBeanFactoryPostProcessor" />
</beans>
这显然是一个非常简单的示例,但在运行测试时,myBean值将设置为"Modified for test"
而不是"this will be overwritten"
。
为每个环境单独定义bean的替代方法是通过添加doWithSpring
闭包覆盖测试类本身内部的bean:
static doWithSpring = {
myBean(String, 'Modified for test')
}
void "test bean is overridden"() {
expect:
grailsApplication.mainContext.getBean('myBean') == 'Modified for test'
}