【问题标题】:Upgrading from Java 8 to 11, why won't spring tests component scan properly?从 Java 8 升级到 11,为什么 spring 测试组件扫描不正确?
【发布时间】:2019-01-24 16:13:48
【问题描述】:

我开始对我们的基础架构进行一些升级,更新一些库以使用 Gradle 5.1(来自 4.2)、Spring Boot 2(来自 1.5)、Java 11(来自 8),然后以使用 Java 11 为目标模块系统。

我已经完成了所有更新,但我的测试在最后一步失败了。看来,当我指示 Gradle 使用模块路径运行测试时,Spring 没有获取我的 @Component 对象,并且我的自动装配失败。

需要明确的是,使用 Java 11 和默认类路径时测试通过,但在我添加如下所示的 compileTestJavatest gradle 任务后失败。 (这些任务基于gradle.org java 9 guide 的示例)代码仍然可以编译(我已经克服了所有与模块相关的构建错误)并且当我收到以下错误时,Spring 上下文会尝试站起来。

当我使用 Spring 启用 JPA 存储库时,它确实会找到这些类(在同一项目的不同包中)并按预期创建它们的单例 bean。但是,当我为需要它正在测试的服务实例的服务运行测试时,它不会创建该 bean。

那么显而易见的问题是为什么我的测试无法再找到要创建的那些类?

build.gradle(修剪)

plugins {
    id 'java'
    id 'com.gradle.build-scan' version "2.1"
    id 'org.springframework.boot' version "2.1.2.RELEASE"
    id 'maven-publish'
}

//sourceCompatibility = '1.8'
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'

if (!hasProperty('mainClass')) {
    ext.mainClass = ''
}

jar {
    enabled = true
    baseName = "my-jar"

    // For embedded tomcat apps
    manifest.attributes provider: 'gradle'
}

compileJava {
    inputs.property("moduleName", "com.mypackage.academics")

    doFirst {
        options.compilerArgs = [
            '--module-path', classpath.asPath,
        ]
        classpath = files()  
    }
}

compileTestJava {
    inputs.property("moduleName", "com.mypackage.academics")
    doFirst {
        options.compilerArgs = [
            '--module-path', classpath.asPath, 
            '--add-modules', 'junit',  
            '--add-reads', "com.mypackage.academics=junit", 
            '--patch-module', "com.mypackage.academics=" + "src/test/resources:" + files(sourceSets.test.java.srcDirs).asPath, 
        ]
        classpath = files()
    }
}

test {
    inputs.property("moduleName", "com.mypackage.academics")
    doFirst {
        jvmArgs = [
            '--module-path', classpath.asPath, 
            '--add-modules', 'ALL-MODULE-PATH', 
            '--add-reads', "com.mypackage.academics=junit,spring.test,org.hamcrest", 
            '--patch-module', "com.mypackage.academics=" + "src/test/resources:" + files(sourceSets.test.java.outputDir).asPath, 
        ]
        classpath = files()
    }
}

module-info.java(已修整)

module com.mypackage.academics {
    exports com.mypackage.academics.config;

    opens com.mypackage.academics.config to org.hibernate.orm.core, spring.core;

    requires spring.beans;
    requires spring.data.commons;
    requires spring.context;
    requires spring.core;
    requires spring.data.jpa;
    requires spring.tx;
}

错误:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.mypackage.academics.config.AcademicsConfigService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at spring.beans@5.1.4.RELEASE/org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1651)
    at spring.beans@5.1.4.RELEASE/org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1210)
    at spring.beans@5.1.4.RELEASE/org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1164)
    at spring.beans@5.1.4.RELEASE/org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:593)
    ... 52 more

【问题讨论】:

  • 没有看到AcademicsConfigService(它是一个接口还是一个实现?如果它是一个具体的类,该类有哪些注释?)或需要AcademicsConfigService的类或你的Spring-Application-初学者,我只能猜测: 1.:尝试打开com.mypackage.academics.configspring.beansspring.context。 2.:确保 Spring 可以找到您的实现类,例如通过将其包含到 Spring-Application-Starter 的 @SpringBootApplication 注释的 scanBasePackages 中。

标签: java spring gradle junit java-module


【解决方案1】:

据我了解,就 Java 11 而言,这是预期的行为。

这个问题在这个线程中讨论。 http://mail.openjdk.java.net/pipermail/core-libs-dev/2018-July/054228.html

基本上,运行测试的方式是在模块路径上设置应用程序类,同时为测试类使用类路径。

【讨论】:

  • 基于 Gradle 的文档,应该通过以下方式解决:'--patch-module', "com.mypackage.academics=" + "src/test/resources:" + files(sourceSets.test.java.srcDirs).asPath
猜你喜欢
  • 2018-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多