1

在将 Spring Framework spring-test 依赖项从 4.2.9 升级到 4.3.9 后,我在运行集成测试时遇到了一些问题。

我正在使用一个 ContextConfiguration 类,它实现了 spring 测试SmartContextLoader,它允许我加载由配置文件拆分的不同 .xml 配置文件。根据当前的 spring 配置文件,它将运行该配置文件的特定 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 弹簧测试版本上不起作用。

4

1 回答 1

1

来自的Javadoc SmartContextLoader.processContextConfiguration(ContextConfigurationAttributes)

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

最后一句中描述的行为是导致您出现问题的原因。

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

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

问候,

Sam(Spring TestContext 框架的作者

于 2017-07-06T16:21:14.777 回答