2016-06-21 2 views
2

Я пытаюсь написать тестовый пример интеграции с Spring Boot Test.Spring Boot test case не использует пользовательскую услугу преобразования

Я настроить ConversionService знать о новых java.time типов:

@Configuration 
public class ConversionServiceConfiguration { 
    @Bean 
    public static ConversionService conversionService() { 
     final FormattingConversionService reg = new DefaultFormattingConversionService(); 
     new DateTimeFormatterRegistrar().registerFormatters(reg); 
     return reg; 
    } 
} 

а затем ожидать, что она работает:

@Component 
class MyServiceConfig { 
    @Value("${max-watch-time:PT20s}") 
    private Duration maxWatchTime = Duration.ofSeconds(20); 
} 

При работе в нормальном SpringApplication.run это, кажется, работает хорошо. Однако, в моем тесте:

@RunWith(SpringRunner.class) 
@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT, classes= { 
    MyServiceMain.class, 
    AttachClientRule.class 
}) 
public class MyTest { 
    @Inject 
    @Rule 
    public AttachClientRule client; 

    @Test(expected=IllegalArgumentException.class) 
    public void testBad() throws Exception { 
     client.doSomethingIllegal(); 
    } 
} 

она взрывается:

Вызванная: org.springframework.beans.factory.UnsatisfiedDependencyException: Ошибка при создании боба с именем 'AttachClientRule': Неудовлетворенная зависимость выражается через параметр конструктора 0:

Ошибка создания компонента с именем «MyServiceConfig»: недопустимая зависимость, выраженная через поле «maxWatchTime»: не удалось преобразовать значение типа [java.lang.String] в требуемый тип [java.time.Duration];

nested exception is java.lang.IllegalStateException: Невозможно преобразовать значение типа [java.lang.String] в требуемый тип [java.time.Duration]: не найдено подходящих редакторов или стратегии конверсии;

Вглядываясь глубоко в кишках TypeConverterDelegate, что делает фактическое преобразование, по-видимому, чтобы захватить ConversionService, используемый с поля на DefaultListableBeanFactory. Настройка наблюдения на котором установлено, что поле, я нахожу AbstractApplicationContext.refresh() метод:

// Allows post-processing of the bean factory in context subclasses. 
postProcessBeanFactory(beanFactory); 
// Invoke factory processors registered as beans in the context. 
invokeBeanFactoryPostProcessors(beanFactory); 
// Register bean processors that intercept bean creation. 
registerBeanPostProcessors(beanFactory); 
// Initialize message source for this context. 
initMessageSource(); 
// Initialize event multicaster for this context. 
initApplicationEventMulticaster(); 
// Initialize other special beans in specific context subclasses. 
onRefresh(); // <--- MyServiceConfig initialized here 
// Check for listener beans and register them. 
registerListeners(); 
// Instantiate all remaining (non-lazy-init) singletons. 
finishBeanFactoryInitialization(beanFactory); // <--- DefaultListableBeanFactory.conversionService set here!!! 
// Last step: publish corresponding event. 
finishRefresh(); 

Так @Value инъекции происходит до того, как ConversionService применяется к BeanFactory. Нет буено!

Я обнаружил, что, кажется, обходной путь:

@Configuration 
public class ConversionServiceConfiguration implements BeanFactoryPostProcessor { 
    @Bean 
    public static ConversionService conversionService() { 
     final FormattingConversionService reg = new DefaultFormattingConversionService(); 
     new DateTimeFormatterRegistrar().registerFormatters(reg); 
     return reg; 
    } 

    @Override 
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { 
     beanFactory.setConversionService(conversionService()); 
    } 
} 

Это заставляет инициализацию произойти раньше, но не чувствует, как правильное решение (по крайней мере, это не документированным как таковой).

Где я пошла не так? Spring 4.3.0, Spring Загрузочный 1.4.0M3

EDIT

И теперь я обнаружил еще один путь к сбою! Не делая тот же класс конфигурации реализации EnvironmentAware:

@Override 
public void setEnvironment(Environment environment) { 
    ((AbstractEnvironment) environment).setConversionService(conversionService()); 
} 

Я считаю, что PropertySourcesPropertyResolver использует неправильно (по умолчанию) ConversionService. Это сводит меня с ума!

Вызванный: java.lang.IllegalArgumentException: Невозможно преобразовать значение [PT15s] от типа источника [String] целевого типа [Продолжительность] в org.springframework.core.env.PropertySourcesPropertyResolver.getProperty (PropertySourcesPropertyResolver.java:94) на org.springframework.core.env.PropertySourcesPropertyResolver.getProperty (PropertySourcesPropertyResolver.java:65) в org.springframework.core.env.AbstractPropertyResolver.getProperty (AbstractPropertyResolver.java:143) в org.springframework.core.env.AbstractEnvironment.getProperty (AbstractEnvironment.java:546) в com.mycorp.DoSomething.go (DoSomething.java:103)

ответ

0

Попытка удалить static ключевое слово из conversionService фасоли определение.

+0

Спасибо, но это не похоже, чтобы помочь. –

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