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

GitHub Actions流水线加载ApplicationContext失败问题求助

GitHub Actions中TestContainers集成测试加载ApplicationContext失败,本地正常

在GitHub Actions流水线运行测试时,出现IllegalState Failed to load ApplicationContext错误,但本地IntelliJ使用Maven执行测试完全正常,仅流水线中两个Repository测试类报错。

CI流水线配置

name: CI workflow

on:
  push:
    branches:
      - main

jobs:
  build-deploy:
    name: Continuous integration with Maven
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup JDK 17
        uses: actions/setup-java@v4
        with:
          distribution: 'zulu'
          java-version: 17

      - name: Unit tests
        run: mvn -B test --file pom.xml

      - name: Build the application
        run: mvn -B package --file pom.xml

报错的测试类

ClassroomRepositoryTest

@Testcontainers
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class ClassroomRepositoryTest {
    @Container
    static MySQLContainer<?> mySQLContainer = new MySQLContainer<>("mysql:8.0.35");

    @Autowired
    ClassroomRepository classroomRepository;

    @BeforeEach
    public void setup() {
        Classroom classroom = Classroom.builder()
                .id(1L)
                .name("math101")
                .subject("mathematics")
                .code("random")
                .build();

        classroomRepository.save(classroom);
    }

    @Test
    public void testConnection() {
        assertTrue(mySQLContainer.isCreated());
        assertTrue(mySQLContainer.isRunning());
    }

    @Test
    public void testFindByCode() {
        Optional<Classroom> classroomOptional = classroomRepository.findClassroomByCode("random");

        assertTrue(classroomOptional.isPresent());
    }

    @Test
    public void testFindByCodeWithInvalidCode() {
        Optional<Classroom> classroomOptional = classroomRepository.findClassroomByCode("wrong-code");

        assertFalse(classroomOptional.isPresent());
    }
}

UserRepositoryTest

@Testcontainers
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class UserRepositoryTest {

    @Container
    private static MySQLContainer<?> mySQLContainer = new MySQLContainer<>("mysql:8.0.35");

    @Autowired
    private UserRepository userRepository;

    @DynamicPropertySource
    static void dynamicProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.datasource.url", mySQLContainer::getJdbcUrl);
        registry.add("spring.datasource.username", mySQLContainer::getUsername);
        registry.add("spring.datasource.password", mySQLContainer::getPassword);
    }

    @BeforeEach
    public void setup() {
        User user = User.builder()
                .id(1L)
                .firstname("John")
                .lastname("Doe")
                .username("john doe")
                .email("john@email.com")
                .password("1234")
                .dateOfBirth(LocalDate.of(1980, 9, 9))
                .build();

        userRepository.save(user);
    }

    @Test
    public void testConnection() {
        assertTrue(mySQLContainer.isCreated());
        assertTrue(mySQLContainer.isRunning());
    }

    @Test
    public void testFindByEmail() {
        Optional<User> userOptional = userRepository.findByEmail("john@email.com");

        assertTrue(userOptional.isPresent());
    }

    @Test
    public void testFindByEmailWithInvalidEmail() {
        Optional<User> userOptional = userRepository.findByEmail("wrong@email.com");

        assertFalse(userOptional.isPresent());
    }
}

GitHub Actions错误日志

核心错误信息

Error:  Errors: 
Error:    ClassBuddyApplicationTests.contextLoads » IllegalState Failed to load ApplicationContext for [WebMergedContextConfiguration@74764622 testClass = com.demo.ClassBuddy.ClassBuddyApplicationTests, locations = [], classes = [com.demo.ClassBuddy.ClassBuddyApplication], contextInitializerClasses = [], activeProfiles = [], propertySourceDescriptors = [], propertySourceProperties = ["org.springframework.boot.test.context.SpringBootTestContextBootstrapper=true"], contextCustomizers = [org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@5b67bb7e, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@3d246ea3, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.web.client.TestRestTemplateContextCustomizer@63611043, 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.WebDriverContextCustomizer@17d88132, org.springframework.boot.test.context.SpringBootTestAnnotation@dbebc8df], resourceBasePath = "src/main/webapp", contextLoader = org.springframework.boot.test.context.SpringBootContextLoader, parent = null]
Error:    ClassroomRepositoryTest.simpleTest » IllegalState ApplicationContext failure threshold (1) exceeded: skipping repeated attempt to load context for [MergedContextConfiguration@35c9e3b9 testClass = com.demo.ClassBuddy.repository.ClassroomRepositoryTest, locations = [], classes = [com.demo.ClassBuddy.ClassBuddyApplication], contextInitializerClasses = [], activeProfiles = [], propertySourceDescriptors = [], propertySourceProperties = ["org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTestContextBootstrapper=true"], contextCustomizers = [[ImportsContextCustomizer@11c27ace key = [org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration, org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration, org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManagerAutoConfiguration, org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration, org.springframework.boot.autoconfigure.sql.init.SqlInitializationAutoConfiguration, org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration, org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration, org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.JdbcClientAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration]], org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@5b67bb7e, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@3d246ea3, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@3ae14048, org.springframework.boot.test.autoconfigure.actuate.observability.ObservabilityContextCustomizerFactory$DisableObservabilityContextCustomizer@1f, org.springframework.boot.test.autoconfigure.filter.TypeExcludeFiltersContextCustomizer@34be3d80, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@a7ab0a43, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizer@17d88132, org.springframework.boot.test.context.SpringBootTestAnnotation@ef828610], contextLoader = org.springframework.boot.test.context.SpringBootContextLoader, parent = null]
Error:    UserRepositoryTest.simpleTest » IllegalState Failed to load ApplicationContext for [MergedContextConfiguration@77aabf26 testClass = com.demo.ClassBuddy.repository.UserRepositoryTest, locations = [], classes = [com.demo.ClassBuddy.ClassBuddyApplication], contextInitializerClasses = [], activeProfiles = [], propertySourceDescriptors = [], propertySourceProperties = ["org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTestContextBootstrapper=true"], contextCustomizers = [[ImportsContextCustomizer@292be875 key = [org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration, org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration, org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManagerAutoConfiguration, org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration, org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration, org.springframework.boot.autoconfigure.sql.init.SqlInitializationAutoConfiguration, org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration, org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration, org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.JdbcClientAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration, org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration]], org.springframework.boot.test.context.filter.ExcludeFilterContextCustomizer@5b67bb7e, org.springframework.boot.test.json.DuplicateJsonObjectContextCustomizerFactory$DuplicateJsonObjectContextCustomizer@3d246ea3, org.springframework.boot.test.mock.mockito.MockitoContextCustomizer@0, org.springframework.boot.test.autoconfigure.OverrideAutoConfigurationContextCustomizerFactory$DisableAutoConfigurationContextCustomizer@3ae14048, org.springframework.boot.test.autoconfigure.actuate.observability.ObservabilityContextCustomizerFactory$DisableObservabilityContextCustomizer@1f, org.springframework.boot.test.autoconfigure.filter.TypeExcludeFiltersContextCustomizer@34be3d80, org.springframework.boot.test.autoconfigure.properties.PropertyMappingContextCustomizer@a7ab0a43, org.springframework.boot.test.autoconfigure.web.servlet.WebDriverContextCustomizer@17d88132, org.springframework.boot.test.context.SpringBootTestAnnotation@ef828610], contextLoader = org.springframework.boot.test.context.SpringBootContextLoader, parent = null]

Maven执行错误

Failed to execute goal org.apache.maven.plugins:maven-surefire-plugin:3.1.2:test (default-test) on project ClassBuddy: 
Error:  
Error:  Please refer to /home/runner/work/class-buddy/class-buddy/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.

排查原因与解决办法

核心原因分析

  1. ClassroomRepositoryTest缺少数据源配置:该测试类仅禁用了默认测试数据库,但未通过@DynamicPropertySource注入TestContainers的MySQL连接信息,导致Spring无法找到有效数据源,加载ApplicationContext失败。本地环境可能存在隐式配置,流水线环境无此条件。
  2. GitHub Actions Runner资源限制:Runner的CPU/内存有限,MySQL容器启动或初始化超时,导致无法建立连接。
  3. Maven Surefire插件兼容性:当前使用的3.1.2版本可能与TestContainers、JUnit5存在兼容性问题。

解决步骤

  1. 给ClassroomRepositoryTest补充数据源配置
    添加和UserRepositoryTest一致的@DynamicPropertySource方法,注入容器连接属性:

    @DynamicPropertySource
    static void dynamicProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.datasource.url", mySQLContainer::getJdbcUrl);
        registry.add("spring.datasource.username", mySQLContainer::getUsername);
        registry.add("spring.datasource.password", mySQLContainer::getPassword);
    }
    
  2. 确保容器完全初始化
    添加@BeforeAll方法,等待MySQL容器启动并可用:

    @BeforeAll
    static void setupContainer() {
        mySQLContainer.start();
        // 验证数据库连接
        try (Connection conn = DriverManager.getConnection(
                mySQLContainer.getJdbcUrl(),
                mySQLContainer.getUsername(),
                mySQLContainer.getPassword()
        )) {
            // 连接成功则继续
        } catch (SQLException e) {
            throw new RuntimeException("测试容器连接失败", e);
        }
    }
    
  3. 升级Maven Surefire插件
    在pom.xml中更新插件版本至最新稳定版(如3.2.5):

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>3.2.5</version>
            </plugin>
        </plugins>
    </build>
    
  4. 增强流水线Docker环境
    在CI配置中显式初始化Docker服务,确保容器运行环境正常:

    - name: Setup Docker
      uses: docker/setup-buildx-action@v3
    
  5. 获取详细错误日志
    修改测试步骤,添加-e参数输出完整堆栈,定位具体错误:

    - name: Unit tests
      run: mvn -B test -e --file pom.xml
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 18:47:05