Skip to content

Instantly share code, notes, and snippets.

@xgp
Created October 28, 2021 08:55
Show Gist options
  • Save xgp/a23f3357ef977c70f6dc6e74a3b3f2e0 to your computer and use it in GitHub Desktop.
Save xgp/a23f3357ef977c70f6dc6e74a3b3f2e0 to your computer and use it in GitHub Desktop.
JUnit4 Keycloak Rule
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
import org.keycloak.admin.client.Keycloak;
import org.keycloak.representations.idm.RealmRepresentation;
public class ExampleTest {
@ClassRule public static KeycloakSuite server = KeycloakSuite.SERVER;
@BeforeClass
public static void commonSetup() {
Keycloak keycloak = server.client();
//do setup here that is common to all tests in this class
}
@Test
public void exampleTest() {
Keycloak keycloak = server.client();
RealmRepresentation realm = keycloak.realm("master").toRepresentation();
assertThat(realm.getId(), is("master"));
}
}
import com.google.common.collect.ObjectArrays;
import com.google.common.io.MoreFiles;
import com.google.common.io.RecursiveDeleteOption;
import java.io.IOException;
import java.net.ServerSocket;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import org.keycloak.OAuth2Constants;
import org.keycloak.admin.client.Keycloak;
import org.keycloak.admin.client.KeycloakBuilder;
import org.keycloak.testsuite.KeycloakServer;
public class KeycloakSuite implements TestRule {
public static final KeycloakSuite SERVER = new KeycloakSuite();
private final AtomicBoolean initialized = new AtomicBoolean();
private KeycloakServer keycloak;
private int port;
@Override
public synchronized Statement apply(Statement base, Description description) {
if (!initialized.get()) {
init();
initialized.set(true);
}
return base;
}
public KeycloakServer getKeycloak() {
return this.keycloak;
}
public int getPort() {
return this.port;
}
public String getAuthUrl() {
return String.format("%sauth", getRootUrl());
}
public String getRootUrl() {
return String.format("http://127.0.0.1:%d/", getPort());
}
private static final String[] ARGS = {};
private static final String[] PROPS = {
"keycloak.bind.address=127.0.0.1",
"java.net.preferIPv4Stack=true",
"keycloak.connectionsJpa.url=jdbc:h2:file:./target/data/keycloak_4_x_master",
"keycloak.connectionsJpa.driver=org.h2.Driver",
"keycloak.connectionsJpa.driverDialect=org.hibernate.dialect.H2Dialect",
"keycloak.connectionsJpa.user=sa",
"keycloak.connectionsJpa.password=",
"profile=COMMUNITY",
"product.default-profile=COMMUNITY",
"keycloak.password.blacklists.path=./target/data/blacklists/",
"com.sun.net.ssl.checkRevocation=false",
"keycloak.product.name=keycloak",
"product.name=keycloak",
"keycloak.profile=preview",
"keycloak.profile.feature.account_api=enabled",
"keycloak.profile.feature.account2=enabled",
"keycloak.profile.feature.scripts=enabled"
};
// "product.version=${keycloak.version}",
private void setSystemProps(String[] props) {
for (String prop : props) {
String[] t = prop.split("=");
String val = t.length < 2 ? "" : t[1];
System.setProperty(t[0], val);
}
}
private void deleteDataDirs() throws IOException {
Path data = Paths.get("./target/data");
if (Files.exists(data)) {
MoreFiles.deleteRecursively(data, RecursiveDeleteOption.ALLOW_INSECURE);
}
}
private void init() {
port = nextFreePort(8082, 10000);
String portProp = String.format("keycloak.port=%d", port);
String[] props = ObjectArrays.concat(PROPS, portProp);
setSystemProps(props);
try {
deleteDataDirs();
keycloak = KeycloakServer.bootstrapKeycloakServer(ARGS);
} catch (Throwable e) {
throw new IllegalStateException("Unable to start KeycloakServer", e);
}
}
private static int nextFreePort(int from, int to) {
for (int port = from; port <= to; port++) {
if (isLocalPortFree(port)) {
return port;
}
}
throw new IllegalStateException("No free port found");
}
private static boolean isLocalPortFree(int port) {
try {
new ServerSocket(port).close();
return true;
} catch (IOException e) {
return false;
}
}
public Keycloak client() {
return getAdminClient(getAuthUrl(), "master", "admin-cli", "admin", "admin");
}
private static Keycloak getAdminClient(
String url, String realm, String clientId, String username, String password) {
Keycloak keycloak =
KeycloakBuilder.builder()
.serverUrl(url)
.realm(realm)
.grantType(OAuth2Constants.PASSWORD)
.clientId(clientId)
.username(username)
.password(password)
.build();
return keycloak;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment