Spring Boot中Keycloak Admin Client测试如何不影响真实Keycloak实例
Keycloak Admin Client 无侵入测试方案
你可以通过以下三种主流方案实现测试逻辑完全不影响真实运行的Keycloak服务:
方案1:使用Testcontainers启动隔离临时Keycloak实例(集成测试首选)
Testcontainers会在测试执行时自动启动一个独立的Keycloak Docker容器,测试结束后容器直接销毁,所有测试数据不会残留,和生产环境完全隔离。
配置步骤:
- 首先引入Testcontainers和Keycloak测试依赖(以Maven为例)
<dependency> <groupId>org.testcontainers</groupId> <artifactId>junit-jupiter</artifactId> <version>匹配你项目的版本</version> <scope>test</scope> </dependency> <dependency> <groupId>org.testcontainers</groupId> <artifactId>keycloak</artifactId> <version>匹配你项目的版本</version> <scope>test</scope> </dependency>
- 修改测试类配置,将Keycloak连接地址指向临时容器实例,可提前导入测试用的Realm配置文件初始化测试环境,修改后的测试代码示例如下:
@SpringBootTest @RunWith(SpringRunner.class) @Testcontainers class ProfilesApplicationTests { // 定义临时Keycloak容器,指定版本和测试Realm导入配置 @Container static KeycloakContainer keycloak = new KeycloakContainer("quay.io/keycloak/keycloak:你的Keycloak版本号") .withRealmImportFile("test-realm-config.json"); // 动态覆盖配置文件中的Keycloak连接地址、管理员账号等配置 @DynamicPropertySource static void registerKeycloakProperties(DynamicPropertyRegistry registry) { registry.add("keycloak.auth-server-url", keycloak::getAuthServerUrl); registry.add("keycloak.admin.username", keycloak::getAdminUsername); registry.add("keycloak.admin.password", keycloak::getAdminPassword); } @Autowired private AccountService accountService; @Autowired private UsersResource usersResource; @Test void testGetAccountById() { UserRepresentation user = new UserRepresentation(); user.setEnabled(true); user.setUsername("tester1"); user.setFirstName("First"); user.setLastName("Last"); user.setEmail("tom+tester1@tdlabs.local"); user.setAttributes(Collections.singletonMap("origin", List.of("demo"))); Response response = usersResource.create(user); String userId = CreatedResponseUtil.getCreatedId(response); Assertions.assertNotNull(accountService.findById(userId)); } }
方案2:Mock Keycloak依赖(单元测试首选)
如果不需要验证和Keycloak的真实交互逻辑,只需要测试自身业务代码,可以直接Mock Keycloak Admin Client相关组件的返回值,不需要启动任何真实Keycloak服务。
示例代码:
@SpringBootTest @RunWith(SpringRunner.class) class ProfilesApplicationTests { @Autowired private AccountService accountService; // 替换真实的UsersResource为Mock对象 @MockBean private UsersResource usersResource; @Test void testGetAccountById() { UserRepresentation user = new UserRepresentation(); user.setEnabled(true); user.setUsername("tester1"); user.setFirstName("First"); user.setLastName("Last"); user.setEmail("tom+tester1@tdlabs.local"); user.setAttributes(Collections.singletonMap("origin", List.of("demo"))); // 打桩Mock返回值 String mockUserId = "test-user-id-123"; Response mockResponse = Response.created(URI.create("/users/" + mockUserId)).build(); when(usersResource.create(any(UserRepresentation.class))).thenReturn(mockResponse); Response response = usersResource.create(user); String userId = CreatedResponseUtil.getCreatedId(response); Assertions.assertNotNull(accountService.findById(userId)); } }
方案3:独立测试Keycloak环境
如果不想使用容器,可单独部署一套测试专用的Keycloak服务,测试配置文件单独指向该环境,和生产配置完全隔离,可单独创建测试专用Realm,测试完成后定期清理测试数据即可。
注意事项
- 不要在测试配置中写入任何生产环境Keycloak的地址、管理员账号等信息,避免配置混用导致污染生产数据
- 若使用独立测试环境,可在测试类中增加测试后清理逻辑,测试结束后自动删除创建的测试用户,避免测试数据堆积
内容的提问来源于stack exchange,提问作者Nate Hiber
相关产品推荐
相关产品推荐

