2016-03-01 2 views
0

Я работаю над пользовательскими загрузчиками Spring Boot. В тестовом стартере я хотел бы выполнить составленную аннотацию, которая добавит дополнительные @Configuration классы в ApplicationContext (и, возможно, воспользуемся этой аннотацией в TestExecutionListener). например:Can @ContextConfiguration в пользовательской аннотации объединяется?

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.TYPE) 
@ContextConfiguration(classes = AdditionalTestConfiguration.class) 
public @interface ComposedAnnotation { 
} 

И использовать это в моем Spring интеграционного теста загрузки:

@RunWith(SpringJUnit4ClassRunner.class) 
@WebIntegrationTest 
@SpringApplicationConfiguration(Application.class) 
@ComposedAnnotation 
public class SomeTest { 
} 

Нет наследования не участвует. К сожалению, это не работает. Я сомневаюсь, что это Spring Spring, а сама Spring Spring.

Есть ли способ достичь ожидаемого результата?

+0

FYI: '@ContextConfiguration (AdditionalTestConfiguration.class)' не компилировать. Атрибут 'value' в' @ ContextConfiguration' является 'String []' расположения файлов XML или скриптов Groovy. –

+0

Спасибо, за улов. Я печатал его сверху. Исправленный. –

ответ

1

Вы правы: это не проблема с Spring Boot. Но это также не проблема с spring-test.

Скорее, это намеченное поведение Весны в целом. Для получения более подробной информации ознакомьтесь с моим ответом на этот вопрос: @ActiveProfiles in meta annotation and on test class not working

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

Однако, я просто придумал трюк , который позволит вам достичь этого. В частности, вы можете создать ApplicationContextInitializer (ACI), который регистрирует один или несколько классов @Configuration. В вашей составленной аннотации вы можете зарегистрировать этот ACI для регистрации всегда присутствующих @Configuration классов. И когда собственно составленная аннотация фактически используется, она может объявлять дополнительные классы @Configuration, как обычно.

Я только что представил рабочий пример в this commit.

В принципе, код будет выглядеть примерно так:

@ContextConfiguration(loader = AnnotationConfigContextLoader.class, initializers = FooConfigInitializer.class) 
@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.TYPE) 
public @interface ComposedContextConfiguration { 

    @AliasFor(annotation = ContextConfiguration.class, attribute = "classes") 
    Class<?>[] value() default {}; 
} 
public class FooConfigInitializer implements ApplicationContextInitializer<GenericApplicationContext> { 

    @Override 
    public void initialize(GenericApplicationContext applicationContext) { 
     new AnnotatedBeanDefinitionReader(applicationContext).register(FooConfig.class); 
    } 
} 

И вы можете использовать его как это:

@RunWith(SpringRunner.class) 
@ComposedContextConfiguration(BarConfig.class) 
public class InitializerConfiguredViaMetaAnnotationTests { /* ... */ } 

Ваш ApplicationContext затем загружается из FooConfig и BarConfig.

Приведенные выше примеры, очевидно, не используют Spring Boot, но те же принципы должны быть применимы и к @SpringApplicationConfiguration.

С уважением,

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

+0

Благодарим вас за объяснение и обмен возможной обходной способ. Я не думаю, что это будет соответствовать моим потребностям. Я хочу добиться того, чтобы реализовать некоторые из функций (* optional *). т. е. я использую Java 8 Clock bean для получения даты и времени: ZonedDateTime.now (часы). В некоторых моих ИТ-системах я хочу использовать FixedClock с определенным значением. Я хотел бы использовать выделенную аннотацию (с параметрами) для этого (настройка @Primary bean переопределяет значение по умолчанию). Я пробовал программно добавлять первичные компоненты в TestExecutionListeners, но у меня были проблемы с этим. Любые предложения по этому поводу? –

Смежные вопросы