2016-06-21 69 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

谢谢,但这似乎并没有帮助。 –