Проблемы пользовательского загрузчика ContextConfiguration при обновлении с Spring Framework 4.2.9 до 4.3+

У меня возникли некоторые проблемы с запуском интеграционных тестов после обновления зависимости весеннего теста Spring Framework с 4.2.9 до 4.3.9.

Я использую класс ContextConfiguration, который реализует весенний тест SmartContextLoader, который позволил мне загружать разные файлы конфигурации .xml, разделенные по профилю. На основе текущего профиля весны он будет запускать определенные компоненты для этого профиля.

Этот 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.


person A Star    schedule 05.07.2017    source источник


Ответы (1)


Из Javadoc SmartContextLoader.processContextConfiguration(ContextConfigurationAttributes):

Примечание: в отличие от стандартного ContextLoader, SmartContextLoader должен предварительно проверить, что сгенерированное или обнаруженное значение по умолчанию действительно существует, прежде чем устанавливать соответствующие свойства местоположения или классов в предоставленных атрибутах ContextConfigurationAttributes. Следовательно, оставление свойства location или class пустым сигнализирует о том, что этот SmartContextLoader не смог сгенерировать или обнаружить значения по умолчанию.

Поведение, описанное в последнем предложении, вызывает у вас проблемы.

Таким образом, решение вашей проблемы будет состоять в том, чтобы фактически реализовать processContextConfiguration() и установить фиктивное местоположение в предоставленном ContextConfigurationAttributes. Это сообщит Spring, что ваш пользовательский загрузчик может правильно определять значения по умолчанию (которые вы жестко кодируете в loadContext()). Затем вы можете удалить фиктивное местоположение из копии mergedContextConfiguration.getLocations() перед передачей их в loadBeanDefinitions().

Это сделало бы его чище для конечных пользователей; однако альтернативой (если у вас действительно нет других конечных пользователей, кроме вас самих) было бы объявление местоположения существующего файла конфигурации XML (через @ContextConfiguration), который просто фактически не объявляет какие-либо bean-компоненты.

С уважением,

Сэм (автор Spring TestContext Framework)

person Sam Brannen    schedule 06.07.2017