使用Terraform部署Spring Boot到EC2时Maven构建失败:无法加载ApplicationContext
问题背景
尝试通过Terraform将Spring Boot应用部署到EC2实例,在GitHub Workflow中执行mvn clean package构建时失败,核心报错为自动生成的TrackerieApplicationTests.contextLoads抛出IllegalStateException,无法加载ApplicationContext,且未编写自定义测试代码。
GitHub Workflow配置
jobs: build: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v2 - name: Set up Java uses: actions/setup-java@v2 with: java-version: '17' distribution: 'adopt' - name: Build Maven project run: mvn clean package
报错信息
[INFO] [INFO] Results: [INFO] Error: Errors: Error:
TrackerieApplicationTests.contextLoads » IllegalState Failed to load
ApplicationContext for [WebMergedContextConfiguration@4dd2ef54
testClass = me.siyum.trackerie.TrackerieApplicationTests, locations =
[], classes = [me.siyum.trackerie.TrackerieApplication],
contextInitializerClasses = [], activeProfiles = [],
propertySourceLocations = [], propertySourceProperties =
["org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true"],
contextCustomizers =
[org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@25641d39,
org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@18df8434,
org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0,
org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@3c77d488,
org.springframework.boot.test.autoconfigure.actuate.observability.ObservabilityContextCustomizerFactory$DisableObservabilityContextCustomizer@1f,
org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@0,
org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizerFactory$Customizer@5d0bf09b,
org.springframework.boot.test.context.SpringBootTestAnnotation@33a0aaa9],
resourceBasePath = "src/main/webapp", contextLoader =
org.springframework.boot.test.context.SpringBootContextLoader, parent
= null] [INFO] Error: Tests run: 1, Failures: 0, Errors: 1, Skipped: 0 [INFO] [INFO]
------------------------------------------------------------------------ [INFO] BUILD FAILURE [INFO]
------------------------------------------------------------------------ [INFO] Total time: 15.067 s [INFO] Finished at: 2023-07-07T04:19:40Z
[INFO]
------------------------------------------------------------------------ Error: Failed to execute goal
org.apache.maven.plugins:maven-surefire-plugin:3.0.0:test
(default-test) on project Trackerie: Error: Error: Please refer to
/home/runner/work/Trackerie-BE/Trackerie-BE/target/surefire-reports
for the individual test results. Error: Please refer to dump files
(if any exist) [date].dump, [date]-jvmRun[N].dump and
[date].dumpstream. Error: -> [Help 1] Error: Error: To see the
full stack trace of the errors, re-run Maven with the -e switch.
Error: Re-run Maven using the -X switch to enable full debug logging.
Error: Error: For more information about the errors and possible
solutions, please read the following articles: Error: [Help 1]
http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
Error: Process completed with exit code 1.
pom.xml内容
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.1.1</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>me.siyum</groupId> <artifactId>Trackerie</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <name>Trackerie</name> <description>Trackerie</description> <properties> <java.version>17</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <version>8.0.33</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <excludes> <exclude> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </exclude> </excludes> </configuration> </plugin> </plugins> </build> </project>
问题原因
Spring Boot初始化项目时自动生成的TrackerieApplicationTests类会尝试加载完整的ApplicationContext,但项目引入了JPA和MySQL依赖,却未配置数据库连接信息(测试环境也没有),导致Spring无法初始化数据源,进而抛出上下文加载失败的异常。
解决方案
1. 跳过测试阶段(最快解决)
直接在Maven构建命令中添加跳过测试的参数,或者在pom.xml中配置插件默认跳过测试:
方式一:修改GitHub Workflow中的Maven命令
将构建步骤的命令改为:
mvn clean package -DskipTests
方式二:在pom.xml中配置surefire插件
在<build><plugins>中添加以下配置,让Maven默认跳过测试:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <skipTests>true</skipTests> </configuration> </plugin>
2. 配置测试用内存数据库
添加H2内存数据库依赖,并配置测试环境的数据库连接,让测试能正常加载上下文:
步骤1:在pom.xml中添加H2依赖
<dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>test</scope> </dependency>
步骤2:创建测试配置文件
在src/test/resources目录下创建application-test.properties,添加H2配置:
spring.datasource.url=jdbc:h2:mem:testdb spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=sa spring.datasource.password= spring.jpa.database-platform=org.hibernate.dialect.H2Dialect spring.h2.console.enabled=true
3. 删除自动生成的测试类
直接删除项目中自动生成的TrackerieApplicationTests.java文件,彻底避免测试阶段执行该类。
内容的提问来源于stack exchange,提问作者Anon

