我应该将配置类注释为@Configuration进行测试吗?

时间:2014-01-10 00:24:40

标签: java spring integration-testing spring-data spring-java-config

我花了一些时间解决Spring Data中缺少org.joda.time.DateTime->java.util.Date转换器的问题(当Joda-Time在类路径上时应该默认启用)。我找到了一个原因,但它在Spring中生成了一个关于@Configuration注释的问题。

使用spring-data-mongodb中的AbstractMongoConfiguration进行标准应用程序配置:

@Configuration
@ComponentScan
@EnableMongoRepositories
public class AppConfig extends AbstractMongoConfiguration { ... }

显式使用AppConfig类的测试(使用Spock,但使用spring-test提供的内部机制):

@ContextConfiguration(classes = AppConfig)
class JodaDocRepositorySpec extends Specification {

    @Autowired
    private JodaDocRepository jodaDocRepository

    def "save document with DateTime"() {
        given:
            def jodaDoc = new JodaDoc(DateTime.now())
        when:
            def savedJodaDoc = jodaDocRepository.save(jodaDoc)
        then:
            savedJodaDoc.id
    }
}

工作正常。但是当AppConfig中的@Configuration注释被删除 /注释时:

//@Configuration
@ComponentScan
@EnableMongoRepositories
public class AppConfig extends AbstractMongoConfiguration { ... }

测试失败了:

org.springframework.core.convert.ConverterNotFoundException:
No converter found capable of converting from type org.joda.time.DateTime to type java.util.Date

AFAIK当配置类在上下文中明确注册时(@Configuration中的类或@ContextConfiguration中的register()方法,不需要使用AnnotationConfigWebApplicationContext )。无论如何都要处理这些类,并找到所有声明的bean。当在不同测试所使用的测试上下文中的相同包中存在2个类似的配置类时,不使用@Configuration来防止通过组件扫描进行检测是有用的。

因此我认为它可能是Spring中的一个错误导致上下文中不同的内部bean处理,具体取决于使用或不是@Configuration注释。我比较了这两种情况下的Spring日志并且存在一些差异,但是我无法确定它们在Spring内部类中引起的是什么。在提交错误之前,我想问一下:

我的问题。是否存在可解释的原因为什么Spring为同一个配置类(在@ContextConfiguration中明确指出)使用(或不使用)Joda-Time的转换器,具体取决于是否存在@Configuration注释?

我还创建了quickstart project来重现这个问题。 spring-data-mongodb 1.3.3,spring 4.0.0,joda-time 2.3。

1 个答案:

答案 0 :(得分:3)

这种行为一切正常。 AbstractMongoConfiguration注释了@Configuration,但实际上这个注释不是@Inherited,因此您必须明确注释您的类。

删除@Configuration注释后,您的AppConfig课程不是完整配置。它仅作为精简配置进行处理,因为它包含@Bean注释的方法 - 请参阅org.springframework.context.annotation.ConfigurationClassUtils

中的方法
  • isFullConfigurationCandidate()
  • isLiteConfigurationCandidate()
  • isFullConfigurationClass()

最后,完整(由@Configuration注释)配置类是进程并由配置后处理器进行增强 - 请查看ConfigurationClassPostProcessor.enhanceConfigurationClasses()