You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复GitHub Actions中测试任务引发的执行错误

GitHub Actions中执行./gradlew build测试失败:属性占位符未正确解析

问题现象

在GitHub Actions工作流中执行./gradlew build时,测试任务失败,错误栈指向PropertyPlaceholderHelper.java:180的IllegalArgumentException,推测是src/test/resources/application.yml中的属性占位符未被正确替换。

错误日志:

Starting a Gradle Daemon (subsequent builds will be faster)
> Task :compileJava
> Task :processResources
> Task :classes
> Task :bootJarMainClassName
> Task :bootJar
> Task :jar
> Task :assemble
> Task :compileTestJava
> Task :processTestResources
> Task :testClasses

> Task :test

GabojaitSpringApplicationTests > contextLoads() FAILED
    java.lang.IllegalStateException at DefaultCacheAwareContextLoaderDelegate.java:132
        Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException at ConstructorResolver.java:800
            Caused by: org.springframework.beans.factory.BeanCreationException at AutowiredAnnotationBeanPostProcessor.java:405
                Caused by: java.lang.IllegalArgumentException at PropertyPlaceholderHelper.java:180

1 test completed, 1 failed

项目目录结构:

|- src
|  |- main
|      |- java
|      |   |- ...
|      |- resources
|          |- application.yml
|- test
    |- java
    |   |- ...
    |- resources
        |- application.yml

GitHub工作流关键配置:

jobs:
  build:
    runs-on: ubuntu-latest
    services:
      mysql:
        image: mysql
        env:
          MYSQL_DATABASE: test_db
          MYSQL_ROOT_PASSWORD: rootpassword
        ports:
          - 3306:3306
        options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3

    steps:
      # ... 其他初始化步骤
      - name: Build with Gradle
        run: ./gradlew build
        env:
          ...
          DB_DDL_TYPE: create
          DB_HOST: localhost
          DB_NAME: test_db
          DB_PASSWORD: rootpassword
          DB_PORT: 3306
          DB_USERNAME: root
          API_NAME: ${{ secrets.API_NAME }}
          ...

测试类代码:

@SpringBootTest
class ApplicationTests {

    @Test
    void contextLoads() {
    }

}

排查与解决方案

1. 核对占位符与环境变量名

PropertyPlaceholderHelper报错基本是因为配置文件里存在未被替换的占位符:

  • 检查src/test/resources/application.yml中的属性键,和GitHub Actions里设置的环境变量名是否完全一致(注意大小写敏感)
  • 核实是否有遗漏的变量,比如API_NAME使用了secrets,要确认仓库中该secrets已正确配置且名称无误

举个例子:如果测试配置写的是api.name: ${API_NAME},但GitHub Actions里拼写为API_NMAE,就会导致替换失败。

2. 确保测试阶段能读取环境变量

Spring Boot测试默认读取系统环境变量,可通过以下方式强化:

  • 在build.gradle中添加配置,让processTestResources任务处理测试资源的占位符:
processTestResources {
    expand(project.properties)
    expand(System.getenv())
}
  • 或者直接在测试类中用@TestPropertySource指定属性:
@SpringBootTest
@TestPropertySource(properties = {
    "db.host=localhost",
    "db.name=test_db",
    // 其他必要属性
})
class ApplicationTests {
    // ...
}

3. 确认MySQL服务就绪

虽然配置了health check,但偶尔会出现MySQL未完全启动就执行测试的情况:

  • 调整MySQL的health check参数,确保检测逻辑准确:
options: --health-cmd="mysqladmin ping -uroot -prootpassword" --health-interval=10s --health-timeout=5s --health-retries=5
  • 或者在构建前添加等待步骤:
- name: 等待MySQL启动完成
  run: |
    until mysqladmin ping -h localhost -u root -prootpassword; do
      echo "等待MySQL中..."
      sleep 5
    done

4. 打印环境变量排查

在GitHub Actions构建步骤中添加打印命令,确认所需变量已正确设置:

- name: 打印环境变量
  run: |
    echo "DB_HOST: $DB_HOST"
    echo "API_NAME: $API_NAME"
    # 其他关键变量也打印出来验证

5. 本地复现问题

在本地模拟GitHub Actions的环境变量,执行./gradlew build:

  • 如果本地正常,说明是GitHub Actions环境的配置问题
  • 如果本地也报错,那就是代码或配置文件本身的问题

内容的提问来源于stack exchange,提问作者gs97ahn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 15:44:56