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

GitHub Actions中Kotlin Spring Boot+MySQL集成测试连接异常排查

问题描述

我正在为一个Kotlin开发、Gradle构建、使用MySQL数据库的Spring Boot项目创建GitHub Actions工作流,用于运行集成测试。但执行构建测试步骤(运行./gradlew clean build)时,所有测试都失败,错误栈如下:

Caused by: java.lang.IllegalStateException at DefaultCacheAwareContextLoaderDelegate.java:98
            Caused by: org.springframework.beans.factory.BeanCreationException at AbstractAutowireCapableBeanFactory.java:1804
                Caused by: javax.persistence.PersistenceException at AbstractEntityManagerFactoryBean.java:421
                    Caused by: org.hibernate.exception.JDBCConnectionException at SQLStateConversionDelegate.java:112
                        Caused by: com.mysql.cj.jdbc.exceptions.CommunicationsException at SQLError.java:174
                            Caused by: com.mysql.cj.exceptions.CJCommunicationsException at NativeConstructorAccessorImpl.java:-2
                                Caused by: java.net.ConnectException at PlainSocketImpl.java:-2

我的gradle.yml配置:

name: CI with Gradle

on: [push]

permissions:
  contents: read

jobs:
  build:

    runs-on: ubuntu-latest
    container: openjdk:11
    services:
      mysql:
        image: mysql:latest

    steps:
    - uses: actions/checkout@v3
    - name: Set up JDK 11
      uses: actions/setup-java@v3
      with:
        java-version: '11'
        distribution: 'temurin'
    - name: Grant execute permission for gradlew
      run: chmod +x gradlew
    - name: Build & Test with Gradle
      uses: gradle/gradle-build-action@v2
      with:
          arguments: build

application.properties配置:

spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/wct?useSSL=true&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=pw
spring.jpa.hibernate.ddl-auto=update
spring.jpa.database=mysql

server.port=8081

失败的JUnit测试示例:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
internal class CustomerControllerTests(
    @Autowired val context: WebApplicationContext,
    @Autowired val mapper: ObjectMapper,
    @Autowired val customerRepository: CustomerRepository,
) {

    private val mvc: MockMvc = (MockMvcBuilders.webAppContextSetup(context).apply<DefaultMockMvcBuilder>(
        SecurityMockMvcConfigurers.springSecurity()).build())

    @Test
    fun `GET customers should return an empty list of customers and 200 OK if one of the required roles is provided`() {
        val response = mvc.perform(
            MockMvcRequestBuilders.get("/customers")
                .contentType(MediaType.APPLICATION_JSON)
        ).andExpect(MockMvcResultMatchers.status().isOk).andReturn().response

       response.contentLength shouldBe 0

    }
}

请问哪里操作有误或遗漏了什么?


问题原因及解决方案

1. GitHub Actions MySQL服务配置不完整

当前的MySQL服务仅指定了镜像,缺少必要的初始化配置和健康检查,导致Spring Boot启动时MySQL还未就绪,且无法通过localhost访问服务。

修正后的MySQL服务配置:

在gradle.yml的services.mysql节点添加环境变量、端口映射和健康检查:

services:
  mysql:
    image: mysql:latest
    env:
      MYSQL_ROOT_PASSWORD: pw  # 和数据库配置中的密码保持一致
      MYSQL_DATABASE: wct      # 提前创建测试所需的数据库
    ports:
      - 3306:3306
    options: >-
      --health-cmd="mysqladmin ping -h localhost"
      --health-interval=10s
      --health-timeout=5s
      --health-retries=3

2. 数据库连接配置错误

GitHub Actions的container模式下,服务容器和Job容器通过服务名通信,而非localhost;同时MySQL默认环境下无需SSL连接(或需额外证书配置),需修改数据库连接配置:

推荐使用测试专用配置文件

创建src/test/resources/application-test.properties,单独配置测试环境的数据库参数:

spring.datasource.url=jdbc:mysql://mysql:3306/wct?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=pw
spring.jpa.hibernate.ddl-auto=create-drop  # 测试结束自动清理数据库,避免脏数据残留

3. 等待MySQL服务完全就绪

在Gradle构建步骤前添加等待逻辑,确保数据库服务完全启动后再执行测试:
在gradle.yml的steps中插入:

- name: Wait for MySQL to be ready
  run: |
    until mysqladmin ping -h mysql -u root -ppw --silent; do
      echo "Waiting for MySQL service..."
      sleep 2
    done
  shell: bash

修正后的完整gradle.yml

name: CI with Gradle

on: [push]

permissions:
  contents: read

jobs:
  build:
    runs-on: ubuntu-latest
    container: openjdk:11
    services:
      mysql:
        image: mysql:latest
        env:
          MYSQL_ROOT_PASSWORD: pw
          MYSQL_DATABASE: wct
        ports:
          - 3306:3306
        options: >-
          --health-cmd="mysqladmin ping -h localhost"
          --health-interval=10s
          --health-timeout=5s
          --health-retries=3

    steps:
    - uses: actions/checkout@v3
    - name: Set up JDK 11
      uses: actions/setup-java@v3
      with:
        java-version: '11'
        distribution: 'temurin'
    - name: Grant execute permission for gradlew
      run: chmod +x gradlew
    - name: Wait for MySQL to be ready
      run: |
        until mysqladmin ping -h mysql -u root -ppw --silent; do
          echo "Waiting for MySQL service..."
          sleep 2
        done
      shell: bash
    - name: Build & Test with Gradle
      uses: gradle/gradle-build-action@v2
      with:
          arguments: build

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 00:01:17