Skip to content

Commit

Permalink
JUnit 5 test framework PoC
Browse files Browse the repository at this point in the history
Closes keycloak#29516

Signed-off-by: stianst <stianst@gmail.com>
  • Loading branch information
stianst committed May 14, 2024
1 parent 6fbe207 commit b5cd4bf
Show file tree
Hide file tree
Showing 35 changed files with 1,137 additions and 2 deletions.
7 changes: 7 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1748,6 +1748,13 @@
</modules>
</profile>

<profile>
<id>test-poc</id>
<modules>
<module>test-poc</module>
</modules>
</profile>

<!-- Profile to activate EAP8 Adapters Build -->
<profile>
<id>eap8-adapters</id>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@
public class QuarkusKeycloakApplication extends KeycloakApplication {

private static final String KEYCLOAK_ADMIN_ENV_VAR = "KEYCLOAK_ADMIN";
private static final String KEYCLOAK_ADMIN_PROP_VAR = "keycloakAdmin";
private static final String KEYCLOAK_ADMIN_PASSWORD_ENV_VAR = "KEYCLOAK_ADMIN_PASSWORD";
private static final String KEYCLOAK_ADMIN_PASSWORD_PROP_VAR = "keycloakAdminPassword";

void onStartupEvent(@Observes StartupEvent event) {
QuarkusPlatform platform = (QuarkusPlatform) Platform.getPlatform();
Expand Down Expand Up @@ -69,8 +71,8 @@ protected void loadConfig() {
}

private void createAdminUser() {
String adminUserName = System.getenv(KEYCLOAK_ADMIN_ENV_VAR);
String adminPassword = System.getenv(KEYCLOAK_ADMIN_PASSWORD_ENV_VAR);
String adminUserName = getEnvOrProp(KEYCLOAK_ADMIN_ENV_VAR, KEYCLOAK_ADMIN_PROP_VAR);
String adminPassword = getEnvOrProp(KEYCLOAK_ADMIN_PASSWORD_ENV_VAR, KEYCLOAK_ADMIN_PASSWORD_PROP_VAR);

if ((adminUserName == null || adminUserName.trim().length() == 0)
|| (adminPassword == null || adminPassword.trim().length() == 0)) {
Expand All @@ -88,4 +90,9 @@ private void createAdminUser() {
}
}

private String getEnvOrProp(String envKey, String propKey) {
String value = System.getenv(envKey);
return value != null ? value : System.getProperty(propKey);
}

}
66 changes: 66 additions & 0 deletions test-poc/base/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?xml version="1.0"?>
<!--
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
~ and other contributors as indicated by the @author tags.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-test-parent</artifactId>
<groupId>org.keycloak.test</groupId>
<version>999.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>keycloak-tests-base</artifactId>
<name>Keycloak Base Tests</name>
<packaging>jar</packaging>
<description/>

<dependencies>
<dependency>
<groupId>org.keycloak.test</groupId>
<artifactId>keycloak-test-junit5-framework</artifactId>
<version>999.0.0-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-suite</artifactId>
<version>1.10.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.logmanager</groupId>
<artifactId>jboss-logmanager</artifactId>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemPropertyVariables>
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
</systemPropertyVariables>
</configuration>
</plugin>
</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package org.keycloak.test.base;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.keycloak.admin.client.Keycloak;
import org.keycloak.common.Profile;
import org.keycloak.representations.info.FeatureRepresentation;
import org.keycloak.test.framework.KeycloakIntegrationTest;
import org.keycloak.test.framework.TestAdminClient;
import org.keycloak.test.framework.server.KeycloakTestServerConfig;

import java.util.Optional;
import java.util.Set;

@KeycloakIntegrationTest(config = CustomConfigTest.CustomServerConfig.class)
public class CustomConfigTest {

@TestAdminClient
Keycloak adminClient;

@Test
public void testUpdateEmailFeatureEnabled() {
Optional<FeatureRepresentation> updateEmailFeature = adminClient.serverInfo().getInfo().getFeatures().stream().filter(f -> f.getName().equals(Profile.Feature.UPDATE_EMAIL.name())).findFirst();
Assertions.assertTrue(updateEmailFeature.isPresent());
Assertions.assertTrue(updateEmailFeature.get().isEnabled());
}

public static class CustomServerConfig implements KeycloakTestServerConfig {

@Override
public Set<String> features() {
return Set.of("update-email");
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.keycloak.test.base;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.keycloak.admin.client.Keycloak;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.test.framework.KeycloakIntegrationTest;
import org.keycloak.test.framework.TestAdminClient;

import java.util.List;

@KeycloakIntegrationTest
public class DefaultConfig1Test {

@TestAdminClient
Keycloak adminClient;

@Test
public void testCreateUser() {
List<RealmRepresentation> realms = adminClient.realms().findAll();
Assertions.assertFalse(realms.isEmpty());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package org.keycloak.test.base;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.keycloak.admin.client.Keycloak;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.test.framework.KeycloakIntegrationTest;
import org.keycloak.test.framework.TestAdminClient;

import java.util.List;

@KeycloakIntegrationTest
public class DefaultConfig2Test {

@TestAdminClient
Keycloak adminClient;

@Test
public void testCreateUser() {
List<RealmRepresentation> realms = adminClient.realms().findAll();
Assertions.assertFalse(realms.isEmpty());
}

}
33 changes: 33 additions & 0 deletions test-poc/base/src/test/java/org/keycloak/test/base/RealmTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package org.keycloak.test.base;

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.keycloak.admin.client.resource.ClientResource;
import org.keycloak.admin.client.resource.RealmResource;
import org.keycloak.test.framework.KeycloakIntegrationTest;
import org.keycloak.test.framework.TestClient;
import org.keycloak.test.framework.TestRealm;
import org.keycloak.test.framework.server.KeycloakTestServerConfig;

import java.util.Map;

@KeycloakIntegrationTest
public class RealmTest {

@TestRealm
RealmResource realmResource;

@TestClient
ClientResource clientResource;

@Test
public void testCreatedRealm() {
Assertions.assertEquals("RealmTest", realmResource.toRepresentation().getRealm());
}

@Test
public void testCreatedClient() {
Assertions.assertEquals("RealmTest", clientResource.toRepresentation().getClientId());
}

}
15 changes: 15 additions & 0 deletions test-poc/base/src/test/resources/logging.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
loggers=org.keycloak.test
logger.org.keycloak.test.level=TRACE

logger.handlers=CONSOLE

handler.CONSOLE=org.jboss.logmanager.handlers.ConsoleHandler
handler.CONSOLE.properties=autoFlush
handler.CONSOLE.level=ERROR
handler.CONSOLE.autoFlush=true
handler.CONSOLE.formatter=PATTERN

# The log format pattern for both logs
formatter.PATTERN=org.jboss.logmanager.formatters.PatternFormatter
formatter.PATTERN.properties=pattern
formatter.PATTERN.pattern=%d{HH:mm:ss,SSS} %-5p %t [%c] %m%n
54 changes: 54 additions & 0 deletions test-poc/framework/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?xml version="1.0"?>
<!--
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
~ and other contributors as indicated by the @author tags.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-test-parent</artifactId>
<groupId>org.keycloak.test</groupId>
<version>999.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>keycloak-test-junit5-framework</artifactId>
<name>Keycloak JUnit 5 testing framework</name>
<packaging>jar</packaging>
<description/>

<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>

<dependencies>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-admin-client</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-junit5</artifactId>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.keycloak.test.framework;

import org.keycloak.test.framework.server.DefaultKeycloakTestServerConfig;
import org.keycloak.test.framework.server.KeycloakTestServerConfig;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface KeycloakIntegrationTest {

Class<? extends KeycloakTestServerConfig> config() default DefaultKeycloakTestServerConfig.class;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package org.keycloak.test.framework;

import org.junit.jupiter.api.extension.AfterAllCallback;
import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.BeforeEachCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.keycloak.test.framework.injection.Registry;

public class KeycloakIntegrationTestExtension implements BeforeAllCallback, AfterAllCallback, BeforeEachCallback {

@Override
public void beforeAll(ExtensionContext context) {
if (isExtensionEnabled(context)) {
getRegistry(context).beforeAll(context.getRequiredTestClass());
}
}

@Override
public void beforeEach(ExtensionContext context) {
if (isExtensionEnabled(context)) {
getRegistry(context).beforeEach(context.getRequiredTestInstance());
}
}

@Override
public void afterAll(ExtensionContext context) {
if (isExtensionEnabled(context)) {
getRegistry(context).afterAll();
}
}

private boolean isExtensionEnabled(ExtensionContext context) {
return context.getRequiredTestClass().isAnnotationPresent(KeycloakIntegrationTest.class);
}

private Registry getRegistry(ExtensionContext context) {
ExtensionContext.Store store = getStore(context);
Registry registry = (Registry) store.getOrComputeIfAbsent(Registry.class, r -> new Registry());
registry.setCurrentContext(context);
return registry;
}

private ExtensionContext.Store getStore(ExtensionContext context) {
while (context.getParent().isPresent()) {
context = context.getParent().get();
}
return context.getStore(ExtensionContext.Namespace.create(getClass()));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.keycloak.test.framework;


import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface TestAdminClient {

}

0 comments on commit b5cd4bf

Please sign in to comment.