从Spring Framework 4.2.9升级到4.3+时,自定义ContextConfiguration Loader会出现问题

时间:2017-07-05 16:03:42

标签: java spring spring-test context-configuration spring-framework-beans

在将Spring Framework弹簧测试依赖项从4.2.9升级到4.3.9之后,我遇到了运行集成测试的一些问题。

我正在使用ContextConfiguration类来实现spring test SmartContextLoader,它允许我加载由配置文件拆分的不同.xml配置文件。根据当前的弹簧配置文件,它将运行该配置文件的特定bean。

ContextConfigurationLoader我在版本4.2.9中运行得非常好,但升级到版本4.3后我正在努力解决此问题。

我包括我在集成测试中创建的ContextConfigurationLoader,如此。

@ContextConfiguration(loader=ContextConfigurationLoader.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class MyIntegrationTest {
     // Test Body
}

ContextConfigurationLoader看起来像这样,

public class ContextConfigurationLoader implements SmartContextLoader {

    @Override
    public void processContextConfiguration(ContextConfigurationAttributes contextConfigurationAttributes) {

    }

    @Override
    public ApplicationContext loadContext(MergedContextConfiguration mergedContextConfiguration) throws Exception {

        GenericXmlApplicationContext context = new GenericXmlApplicationContext();

        context.getEnvironment().setActiveProfiles(mergedContextConfiguration.getActiveProfiles());

        new XmlBeanDefinitionReader(context).
                loadBeanDefinitions(mergedContextConfiguration.getLocations());

        context.load(
                "/development.xml",
                "/staging.xml",
                "/production.xml",
        );

        AnnotationConfigUtils.registerAnnotationConfigProcessors(context);

        context.refresh();
        context.registerShutdownHook();

        return context;
    }

    @Override
    public String[] processLocations(Class<?> aClass, String... strings) {
        return new String[0];
    }

    @Override
    public ApplicationContext loadContext(String... strings) throws Exception {
        ApplicationContext context = ApplicationContextFactory.create();

        context.getBean("dbUnitDatabaseConnection");
        return ApplicationContextFactory.create();
    }
}

最后,这是我尝试运行测试后得到的错误响应。

java.lang.IllegalStateException: ContextConfigurationLoader was unable to detect defaults, and no ApplicationContextInitializers or ContextCustomizers were declared for context configuration attributes [[ContextConfigurationAttributes@53ca01a2 declaringClass = 'com.class.path.to.MyIntegrationTest', classes = '{}', locations = '{}', inheritLocations = true, initializers = '{}', inheritInitializers = true, name = [null], contextLoaderClass = 'com.class.path.to.ContextConfigurationLoader']]

感谢您的帮助,如果您需要更多信息,请与我们联系。

我发现的一个解决方案是将所有.xml配置文件包含在一个文件中并使用@ContextConfiguration这样的注释。

@ContextConfiguration("/config.xml")

但是这需要对测试之外的其余代码进行一些其他更改。这也没有帮助解释为什么我当前的实现不适用于最新的Spring Framework弹簧测试版本。

1 个答案:

答案 0 :(得分:1)

来自SmartContextLoader.processContextConfiguration(ContextConfigurationAttributes)的Javadoc:

  

注意:与标准ContextLoader相比,SmartContextLoader必须在提供的ContextConfigurationAttributes中设置相应的位置或类属性之前,先抢先验证生成的或检测到的默认值是否存在。因此,将位置或类属性保留为空信号表示此SmartContextLoader无法生成或检测默认值。

最后一句中描述的行为是造成问题的原因。

因此,您的问题的解决方案是实际实施processContextConfiguration()并在提供的ContextConfigurationAttributes中设置虚假位置。这将指示Spring您的自定义加载程序能够正确检测默认值(您在loadContext()中硬编码)。然后,您可以从mergedContextConfiguration.getLocations()的副本中删除虚假位置,然后再将其传递给loadBeanDefinitions()

这将使最终用户更清洁;但是,另一种选择(如果你真的没有自己以外的任何最终用户)将声明现有的XML配置文件的位置(通过@ContextConfiguration),它实际上并没有声明任何bean。

此致

Sam( Spring TestContext Framework的作者