我有个奇怪的问题。我们的项目已经启动和运行了6年,一些软件包的升级已经拖延了很久。应用后端用Java 8编写,测试用Java和Groovy编写,前端用AngularJS 1.5编写
App由7个模块组成,整个项目结构和构建过程是通过gradle构建文件来建立的。
在更新库版本的过程中,最大的一个是mongodb从4.0升级到5.1.3和spring_boot版本,从E 1101.2.6升级到2.1.1E 211。
我知道,有相当多的重大升级,多亏了我们所有的测试,我成功地修改了所有代码,以适应新版本库中的更改。所有的测试都通过了。几乎所有模块的构建都很有魅力。(除外)用于一个由Groovy测试类组成的模块。当我从IntelliJ运行它们时,所有的测试都是通过的,没有编译或构建错误。
但是当我尝试运行gradle build时,任务testCompileGroovy失败了,因为其中一个抽象测试规范类中的导入无法被解析。它是@SpringBootTest注释的类参数所需的主Application类的导入。
下面是包含我们所依赖的所有库的libraries.gradle文件.
ext {
spring_version = "5.1.3.RELEASE"
spring_boot_version = "2.1.1.RELEASE"
spring_data_mongodb = "2.1.3.RELEASE"
groovy_version = "2.4.5"
ext.lib = [
spring_core : "org.springframework:spring-core:$spring_version",
spring_context : "org.springframework:spring-context:$spring_version",
spring_context_support : "org.springframework:spring-context-support:$spring_version",
spring_test : "org.springframework:spring-test:$spring_version",
spring_data_mongodb : "org.springframework.data:spring-data-mongodb:$spring_data_mongodb",
spring_shell : "org.springframework.shell:spring-shell:1.1.0.RELEASE",
spring_webmvc : "org.springframework:spring-webmvc:$spring_version",
spring_web : "org.springframework:spring-web$spring_version",
spring_boot_test : "org.springframework.boot:spring-boot-test:2.1.1.RELEASE",
spring_boot_starter : "org.springframework.boot:spring-boot-starter:$spring_boot_version",
spring_boot_starter_web : "org.springframework.boot:spring-boot-starter-web:$spring_boot_version",
spring_boot_starter_tomcat : "org.springframework.boot:spring-boot-starter-tomcat:$spring_boot_version",
spring_boot_starter_security: "org.springframework.boot:spring-boot-starter-security:$spring_boot_version",
spring_boot_starter_test : "org.springframework.boot:spring-boot-starter-test:$spring_boot_version",
spring_boot_gradle_plugin : "org.springframework.boot:spring-boot-gradle-plugin:$spring_boot_version",
spring_boot_autoconfigure : "org.springframework.boot:spring-boot-autoconfigure:$spring_boot_version",
spring_boot_logging : "org.springframework.boot:spring-boot-logging:$spring_boot_version",
swager : "io.springfox:springfox-swagger2:2.6.1",
swager_ui : "io.springfox:springfox-swagger-ui:2.6.1",
groovy_all : "org.codehaus.groovy:groovy-all:$groovy_version",
groovy_sql : dependencies.create("org.codehaus.groovy:groovy-sql:$groovy_version") {
exclude group: "org.codehaus.groovy"
},
http_builder : "org.codehaus.groovy.modules.http-builder:http-builder:0.7.1",
httpmime : "org.apache.httpcomponents:httpmime:4.3.6",
gmongo : dependencies.create("com.gmongo:gmongo:1.5") {
exclude group: "org.codehaus.groovy"
},
postgresql : "org.postgresql:postgresql:9.4-1201-jdbc41",
bonecp : "com.jolbox:bonecp:0.8.0.RELEASE",
joda_time : "joda-time:joda-time:2.8.2",
guava : "com.google.guava:guava:18.0",
gson : "com.google.code.gson:gson:2.8.5",
stripe : "com.stripe:stripe-java:1.37.0",
jackson_annotations : "com.fasterxml.jackson.core:jackson-annotations:2.4.4",
logentries : "com.logentries:logentries-appender:1.1.30",
hibernate_validator : "org.hibernate:hibernate-validator:5.4.2.Final",
logback_classic : "ch.qos.logback:logback-classic:1.1.3",
commons_lang : "org.apache.commons:commons-lang3:3.1",
commons_io : "commons-io:commons-io:2.4",
commons_validator : "commons-validator:commons-validator:1.4.0",
httpclient : "org.apache.httpcomponents:httpclient:4.5.1",
jasypt : "org.jasypt:jasypt:1.9.2",
jsoup : "org.jsoup:jsoup:1.8.3",
trimou_core : "org.trimou:trimou-core:1.8.2.Final",
jackson_core : "com.fasterxml.jackson.core:jackson-core:2.9.8",
jackson_databind : "com.fasterxml.jackson.core:jackson-databind:2.9.8",
jackson_annotations : "com.fasterxml.jackson.core:jackson-annotations:2.9.8",
jackson_datatype_joda : "com.fasterxml.jackson.datatype:jackson-datatype-joda:2.9.8",
google_api_services_gmail : dependencies.create("com.google.apis:google-api-services-gmail:v1-rev23-1.19.1") {
exclude group: "com.google.guava"
},
google_http_client_jackson : dependencies.create("com.google.http-client:google-http-client-jackson:1.19.0") {
exclude group: "com.fasterxml.jackson.core"
},
javax_mail : "com.sun.mail:javax.mail:1.5.4",
dnsjava : "dnsjava:dnsjava:2.1.7",
email_reply_parser : "./lib/EmailReplyParser-1.1.jar",
salesforce : ["com.force.api:force-wsc:31.0.0", "com.force.api:force-partner-api:29.0.0", "com.force.api:force-metadata-api:29.0.0"],
authy : 'com.authy:authy-java:1.1.0',
libphonenumber : 'com.googlecode.libphonenumber:libphonenumber:7.2.4',
hellosign : 'com.hellosign:hellosign-java-sdk:4.0.5',
awaitility : 'com.jayway.awaitility:awaitility:1.7.0',
junit : "junit:junit:4.12",
hamcrest_all : "org.hamcrest:hamcrest-all:1.3",
hamcrest_core : "org.hamcrest:hamcrest-core:1.3",
mockito_core : "org.mockito:mockito-core:1.10.19",
httpmime : "org.apache.httpcomponents:httpmime:4.3.6",
rest_assured : dependencies.create("com.jayway.restassured:rest-assured:2.4.1") {
exclude group: "org.codehaus.groovy"
},
spock_core : "org.spockframework:spock-core:1.2-groovy-2.4",
spock_spring : "org.spockframework:spock-spring:1.2-groovy-2.4",
apache_pdf : "org.apache.pdfbox:pdfbox:2.0.4",
google_cloud : "com.google.cloud:google-cloud-storage:1.35.0"
]}这是build.gradle文件,用于失败的测试-api模块。
apply plugin: 'groovy'
apply plugin: 'java'
apply plugin: 'org.springframework.boot'
repositories {
mavenCentral()
maven {
url "http://repo.springsource.org/libs-release"
}
}
dependencies {
compile project(':api')
compile project(':cli')
compile lib.groovy_all
compile lib.http_builder
compile lib.httpmime
compile lib.gmongo
compile lib.hamcrest_core
testCompile lib.groovy_all
testCompile lib.junit
testCompile lib.spock_core
testCompile lib.spock_spring
testCompile lib.spring_boot_starter_test
}build.gradle for api模块如下所示:
apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'org.springframework.boot'
buildscript {
repositories {
maven {
url "http://repo.springsource.org/libs-release"
}
mavenLocal()
}
dependencies {
classpath lib.spring_boot_gradle_plugin
}
}
repositories {
mavenCentral()
maven {
url "http://repo.springsource.org/libs-release"
}
}
war {
baseName = 'buyerdeck-api'
version = '2.0'
}
dependencies {
compile project(':backend')
compile project(':analytics')
compile lib.spring_webmvc
compile lib.spring_boot_starter
compile lib.spring_boot_starter_web
compile lib.spring_boot_starter_tomcat
compile lib.spring_boot_starter_security
compile lib.jackson_core
compile lib.jackson_annotations
compile lib.jackson_datatype_joda
compile lib.swager
compile lib.swager_ui
testCompile lib.junit
testCompile lib.hamcrest_all
testCompile lib.mockito_core
}
springBoot {
mainClassName = "com.buyerdeck.Application"
}和build.gradle的后端模块:
apply plugin: 'java'
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories {
mavenCentral()
maven {
url "http://repo.springsource.org/libs-release"
}
}
configurations {
all*.exclude module: "groovy"
}
dependencies {
compile project(':email')
compile lib.spring_core
compile lib.spring_context
compile lib.spring_context_support
compile lib.spring_data_mongodb
compile lib.joda_time
compile lib.guava
compile lib.gson
compile lib.stripe
compile lib.jackson_core
compile lib.jackson_databind
compile lib.jackson_annotations
compile lib.logentries
compile lib.hibernate_validator
compile lib.logback_classic
compile lib.commons_lang
compile lib.commons_io
compile lib.commons_validator
compile lib.httpclient
compile lib.salesforce
compile lib.jasypt
compile lib.jsoup
compile lib.trimou_core
compile lib.hellosign
compile lib.awaitility
compile lib.authy
compile lib.libphonenumber
compile lib.httpmime
compile lib.apache_pdf
compile lib.google_cloud
testCompile lib.spring_test
testCompile lib.spring_boot_test
testCompile lib.spring_boot_starter
testCompile lib.junit
testCompile lib.hamcrest_all
testCompile lib.mockito_core
testCompile lib.httpmime
testCompile lib.rest_assured
}
task wrapper(type: Wrapper) {
gradleVersion = '1.11'
}
sourceSets {
test {
java {
srcDir 'src/test/java'
srcDir 'src/test-integration/java'
}
}
}最后,抛出编译错误的类是来自ApiSpecification.groovy测试-api模块的类:
package tests.api
import com.companyxyz.Application
import com.companyxyz.backend.core.tenant.Tenant
import com.companyxyz.backend.infrastructure.mongo.MongoSetup
import org.bson.types.ObjectId
import org.junit.runner.RunWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
import org.springframework.boot.test.context.ConfigFileApplicationContextInitializer
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.boot.web.server.LocalServerPort
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.PropertySource
import org.springframework.data.mongodb.core.MongoTemplate
import org.springframework.data.mongodb.core.query.Criteria
import org.springframework.data.mongodb.core.query.Query
import org.springframework.test.context.ContextConfiguration
import org.springframework.test.context.junit4.SpringRunner
import org.springframework.test.context.web.WebAppConfiguration
import spock.lang.Specification
@PropertySource("classpath:companyxyz.properties")
@SpringBootTest(classes = Application, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT, properties = ["server.port:0", "mongo.database:companyxyz-test-api", "email.templates.root.path:../email-templates", "email.enabled:false", "timegate.enabled:true"])
abstract class ApiSpecification extends Specification {
@LocalServerPort
private int serverPort
@Value('${mongo.database}')
private String dbName
@Autowired
MongoTemplate mongoTemplate;
@Autowired
MongoSetup mongoSetup;
private static boolean dbCleaned;
def setup() {
ApiSettings.apiUrl = "http://localhost:$serverPort/api/"
ApiSettings.dbName = dbName
println "apiurl $ApiSettings.apiUrl"
if (!dbCleaned) {
println "Dropping Mongo DB $dbName"
mongoTemplate.getDb().drop();
mongoSetup.ensureIndexes()
dbCleaned = true;
}
DbExecutor.createMockThingies()
}
def removeUser(email) {
mongoTemplate.remove(Query.query(Criteria.where("email").is(email)), com.companyxyz.backend.core.user.User.class)
}
}错误出现在第3行:
导入com.companyxyz.Application
无法解析导入。testGroovyCompile任务只是由于未解决的依赖关系而失败。直接从扩展该类的类运行测试,没有任何问题。
除了添加了春季测试所需的一个依赖项外,模块的build.gradle文件中没有任何内容未被更改,但其他所有内容都与以前相同。该模块依赖于其他模块,但除了所需的测试依赖之外,它们的构建文件并没有发生太大变化。
我花了好几个小时来解决这个问题,但我只是不明白为什么它不起作用。我尝试了不同的分级版本,但没有成功。有没有人知道这些问题的原因是什么?
很抱歉有这么长的帖子,如果我能提供更多的信息,请告诉我。
卢卡
发布于 2019-01-07 15:03:48
问题是您的api模块是Spring项目:默认情况下,它不会生成标准的jar,而是只生成可执行/胖jar (如果应用了war插件,则生成war )。即使在compile project(':api')模块中添加了“项目”依赖项,Gradle也无法从api模块向tests-api类路径提供类,因为没有从api模块构建的标准jar (请参阅关于项目依赖类型这里的更多详细信息):
Project“lib”依赖项是执行依赖项的一种特殊形式。它将首先生成另一个项目,并将jar与其他项目的类一起添加到类路径中。它还将其他项目的依赖项添加到类路径中。
因此,为了解决你的问题,我看到了两个选择:
1) (首选)在SpringBoot模块中配置api插件以生成标准的jar
来自api模块的build.gradle:
jar {
enabled = true
}2)创建从tests-api到api模块的依赖关系SourceSet:
来自tests模块的build.gradle:
dependencies {
compile project(':api').sourceSets.main.output
// others
}(解决方案2应该工作,但不经过测试。可能导致api项目依赖项在tests-api模块中不可用时出错)
https://stackoverflow.com/questions/54074903
复制相似问题