2016-06-21 23 views
2

我想用Spring Boot Test寫出一個集成測試用例。春季啓動測試用例不使用自定義轉換服務

我定製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'的Bean的錯誤:通過字段'maxWatchTime'表示的不滿意的依賴項:無法將類型[java.lang.String]的值轉換爲所需的類型[java.time.Duration];

嵌套異常是java.lang.IllegalStateException:無法將[java.lang.String]類型的值轉換爲所需類型[java.time.Duration]:找不到匹配的編輯器或轉換策略;

深窺視到執行實際轉換TypeConverterDelegate的膽量,似乎捕捉到從外地用在DefaultListableBeanFactoryConversionService。設置在哪裏該字段設置一個觀察點,我覺得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(); 

所以前ConversionService應用到BeanFactory@Value注入正在發生的事情。沒有bueno!

我發現似乎是一種解決方法:

@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()); 
    } 
} 

這迫使初始化早些時候發生,但並不覺得自己是正確的解決方案(至少它沒有記載這樣)。

我哪裏出錯了? 春天4.3.0,春天引導1.4.0M3

編輯

而現在我發現另一種方式爲它失敗!未做相同的配置類實現EnvironmentAware

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

我發現PropertySourcesPropertyResolver使用錯誤的(默認)ConversionService。這讓我很生氣!

引起:java.lang.IllegalArgumentException異常:在org.springframework.core.env無法轉換值[PT15s]從源類型[字符串]爲目標類型[時間] 。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

嘗試從conversionService豆除去static關鍵字定義。

+0

謝謝,但這似乎並沒有幫助。 –