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

Spring Boot测试中如何清理Keycloak测试容器的数据库?

解决Testcontainers中Keycloak测试后的清理问题

方法一:通过Keycloak Admin API删除用户(推荐)

这种方式贴合Keycloak的官方使用规范,避免直接操作底层数据库带来的版本兼容性问题。

  1. 添加Keycloak Admin Client依赖
    在pom.xml(Maven)中加入对应依赖:
<dependency>
    <groupId>org.keycloak</groupId>
    <artifactId>keycloak-admin-client</artifactId>
    <version>${keycloak.version}</version>
    <scope>test</scope>
</dependency>
  1. 初始化Admin Client连接
    在测试类中,通过容器提供的参数构建Admin Client:
private Keycloak keycloakAdminClient;

@BeforeEach
void initKeycloakAdmin() {
    keycloakAdminClient = KeycloakBuilder.builder()
            .serverUrl(keycloakContainer.getAuthServerUrl())
            .realm("master")
            .username(keycloakContainer.getAdminUsername())
            .password(keycloakContainer.getAdminPassword())
            .clientId("admin-cli")
            .grantType(OAuth2Constants.PASSWORD)
            .build();
}
  1. 在@AfterEach中清理用户
    如果测试中记录了创建的用户名/ID,可精准删除;也可批量清除测试realm中的非初始用户:
@AfterEach
void cleanKeycloakUsers() {
    String testRealm = "your-test-realm"; // 替换为你导入的realm名称

    // 方式1:删除指定测试用户(需提前保存用户ID)
    // keycloakAdminClient.realm(testRealm).users().get(targetUserId).remove();

    // 方式2:批量清除测试realm中所有非初始用户
    List<UserRepresentation> users = keycloakAdminClient.realm(testRealm).users().list();
    for (UserRepresentation user : users) {
        // 排除预先导入的固定用户,比如admin或基础测试用户
        if (!"initial-test-user".equals(user.getUsername())) {
            keycloakAdminClient.realm(testRealm).users().get(user.getId()).remove();
        }
    }

    keycloakAdminClient.close();
}

方法二:直接操作Keycloak数据库(适合熟悉表结构的场景)

如果Keycloak使用外部数据库(如你项目中的MariaDB),可复用业务库的清理逻辑;若使用默认内置H2数据库,需按以下步骤操作:

  1. 获取H2数据库连接信息
    Keycloak默认开启H2 TCP连接,端口为9092,需根据容器映射端口构建JDBC URL:
  • WildFly版Keycloak数据路径:/opt/jboss/keycloak/standalone/data/keycloak
  • Quarkus版Keycloak数据路径:/opt/keycloak/data/keycloak
  1. 编写清理SQL脚本
    创建clean_up_keycloak.sql,清理用户及关联表数据:
-- 删除非初始用户
DELETE FROM USER_ WHERE USERNAME NOT IN ('admin', 'initial-test-user');
-- 清理关联映射表
DELETE FROM USER_ROLE_MAPPING WHERE USER_ID NOT IN (SELECT ID FROM USER_ WHERE USERNAME IN ('admin', 'initial-test-user'));
DELETE FROM USER_ATTRIBUTE WHERE USER_ID NOT IN (SELECT ID FROM USER_ WHERE USERNAME IN ('admin', 'initial-test-user'));
  1. 在@AfterEach中执行脚本
@AfterEach
public void cleanUpKeycloakDb() throws Exception {
    String dbPath = "/opt/keycloak/data/keycloak"; // 根据Keycloak版本调整
    String jdbcUrl = String.format("jdbc:h2:tcp://%s:%d/%s",
            keycloakContainer.getHost(), keycloakContainer.getMappedPort(9092), dbPath);
    
    try (Connection connection = DriverManager.getConnection(jdbcUrl, "sa", "")) {
        Resource resource = new ClassPathResource("/clean_up_keycloak.sql");
        ScriptUtils.executeSqlScript(connection, resource);
    }
}

注意事项

  • 优先选择Admin API方式,Keycloak表结构可能随版本变更,直接操作数据库存在失效风险;
  • 若Keycloak使用外部数据库(如MariaDB),需在容器初始化时指定数据库配置,复用业务库的连接方式清理即可。

内容的提问来源于stack exchange,提问作者Mátyás

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 00:27:11