mirror of
https://github.com/keycloak/keycloak.git
synced 2026-01-09 15:02:05 -03:30
Support running test methods on the server side (#44937)
Closes #44936 Signed-off-by: stianst <stianst@gmail.com>
This commit is contained in:
parent
9597537bf3
commit
aa6890f539
@ -1,8 +1,8 @@
|
||||
package org.keycloak.testframework;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.keycloak.testframework.annotations.KeycloakIntegrationTest;
|
||||
import org.keycloak.testframework.injection.Registry;
|
||||
|
||||
import org.junit.jupiter.api.extension.AfterAllCallback;
|
||||
@ -10,82 +10,82 @@ import org.junit.jupiter.api.extension.AfterEachCallback;
|
||||
import org.junit.jupiter.api.extension.BeforeAllCallback;
|
||||
import org.junit.jupiter.api.extension.BeforeEachCallback;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||
import org.junit.jupiter.api.extension.InvocationInterceptor;
|
||||
import org.junit.jupiter.api.extension.ParameterContext;
|
||||
import org.junit.jupiter.api.extension.ParameterResolutionException;
|
||||
import org.junit.jupiter.api.extension.ParameterResolver;
|
||||
import org.junit.jupiter.api.extension.ReflectiveInvocationContext;
|
||||
import org.junit.jupiter.api.extension.TestWatcher;
|
||||
|
||||
public class KeycloakIntegrationTestExtension implements BeforeAllCallback, BeforeEachCallback, AfterEachCallback, AfterAllCallback, TestWatcher {
|
||||
public class KeycloakIntegrationTestExtension implements BeforeAllCallback, BeforeEachCallback, AfterEachCallback, AfterAllCallback, TestWatcher, InvocationInterceptor, ParameterResolver {
|
||||
|
||||
private static final LogHandler logHandler = new LogHandler();
|
||||
|
||||
@Override
|
||||
public void beforeAll(ExtensionContext context) {
|
||||
if (isExtensionEnabled(context)) {
|
||||
logHandler.beforeAll(context);
|
||||
}
|
||||
logHandler.beforeAll(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeEach(ExtensionContext context) {
|
||||
if (isExtensionEnabled(context)) {
|
||||
logHandler.beforeEachStarting(context);
|
||||
getRegistry(context).beforeEach(context.getRequiredTestInstance());
|
||||
logHandler.beforeEachCompleted(context);
|
||||
}
|
||||
logHandler.beforeEachStarting(context);
|
||||
getRegistry(context).beforeEach(context.getRequiredTestInstance(), context.getRequiredTestMethod());
|
||||
logHandler.beforeEachCompleted(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterEach(ExtensionContext context) {
|
||||
if (isExtensionEnabled(context)) {
|
||||
logHandler.afterEachStarting(context);
|
||||
getRegistry(context).afterEach();
|
||||
logHandler.afterEachCompleted(context);
|
||||
}
|
||||
logHandler.afterEachStarting(context);
|
||||
getRegistry(context).afterEach();
|
||||
logHandler.afterEachCompleted(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterAll(ExtensionContext context) {
|
||||
if (isExtensionEnabled(context)) {
|
||||
logHandler.afterAll(context);
|
||||
getRegistry(context).afterAll();
|
||||
}
|
||||
logHandler.afterAll(context);
|
||||
getRegistry(context).afterAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testFailed(ExtensionContext context, Throwable cause) {
|
||||
if (isExtensionEnabled(context)) {
|
||||
logHandler.testFailed(context);
|
||||
}
|
||||
logHandler.testFailed(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testDisabled(ExtensionContext context, Optional<String> reason) {
|
||||
if (isExtensionEnabled(context)) {
|
||||
logHandler.testDisabled(context);
|
||||
}
|
||||
logHandler.testDisabled(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testSuccessful(ExtensionContext context) {
|
||||
if (isExtensionEnabled(context)) {
|
||||
logHandler.testSuccessful(context);
|
||||
}
|
||||
logHandler.testSuccessful(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testAborted(ExtensionContext context, Throwable cause) {
|
||||
if (isExtensionEnabled(context)) {
|
||||
logHandler.testAborted(context);
|
||||
}
|
||||
logHandler.testAborted(context);
|
||||
}
|
||||
|
||||
private boolean isExtensionEnabled(ExtensionContext context) {
|
||||
return context.getRequiredTestClass().isAnnotationPresent(KeycloakIntegrationTest.class);
|
||||
@Override
|
||||
public void interceptTestMethod(Invocation<Void> invocation, ReflectiveInvocationContext<Method> invocationContext, ExtensionContext extensionContext) throws Throwable {
|
||||
getRegistry(extensionContext).intercept(invocation, invocationContext);
|
||||
}
|
||||
|
||||
private Registry getRegistry(ExtensionContext context) {
|
||||
public static Registry getRegistry(ExtensionContext context) {
|
||||
ExtensionContext.Store store = context.getRoot().getStore(ExtensionContext.Namespace.GLOBAL);
|
||||
Registry registry = (Registry) store.getOrComputeIfAbsent(Registry.class, r -> new Registry());
|
||||
registry.setCurrentContext(context);
|
||||
return registry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext context) throws ParameterResolutionException {
|
||||
return getRegistry(context).supportsParameter(parameterContext, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext context) throws ParameterResolutionException {
|
||||
// As this is only used by custom test executors for now they are responsible for injecting the parameter, hence returning null here
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,18 @@
|
||||
package org.keycloak.testframework;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
import org.keycloak.testframework.injection.Registry;
|
||||
|
||||
public interface TestFrameworkExecutor {
|
||||
|
||||
List<Class<?>> getMethodValueTypes(Method method);
|
||||
|
||||
boolean supportsParameter(Method method, Class<?> parameterType);
|
||||
|
||||
boolean shouldExecute(Method testMethod);
|
||||
|
||||
void execute(Registry registry, Class<?> testClass, Method testMethod);
|
||||
|
||||
}
|
||||
@ -5,11 +5,15 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.keycloak.testframework.KeycloakIntegrationTestExtension;
|
||||
import org.keycloak.testframework.server.DefaultKeycloakServerConfig;
|
||||
import org.keycloak.testframework.server.KeycloakServerConfig;
|
||||
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
@ExtendWith({KeycloakIntegrationTestExtension.class})
|
||||
public @interface KeycloakIntegrationTest {
|
||||
|
||||
Class<? extends KeycloakServerConfig> config() default DefaultKeycloakServerConfig.class;
|
||||
|
||||
@ -2,6 +2,7 @@ package org.keycloak.testframework.injection;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
@ -9,6 +10,7 @@ import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.Set;
|
||||
|
||||
import org.keycloak.testframework.TestFrameworkExecutor;
|
||||
import org.keycloak.testframework.TestFrameworkExtension;
|
||||
import org.keycloak.testframework.config.Config;
|
||||
|
||||
@ -22,6 +24,7 @@ public class Extensions {
|
||||
private final List<Class<?>> alwaysEnabledValueTypes;
|
||||
|
||||
private static Extensions INSTANCE;
|
||||
private final List<TestFrameworkExtension> extensions;
|
||||
|
||||
public static Extensions getInstance() {
|
||||
if (INSTANCE == null) {
|
||||
@ -35,7 +38,7 @@ public class Extensions {
|
||||
}
|
||||
|
||||
private Extensions() {
|
||||
List<TestFrameworkExtension> extensions = loadExtensions();
|
||||
extensions = loadExtensions();
|
||||
valueTypeAlias = loadValueTypeAlias(extensions);
|
||||
Config.registerValueTypeAlias(valueTypeAlias);
|
||||
logger = new RegistryLogger(valueTypeAlias);
|
||||
@ -55,6 +58,19 @@ public class Extensions {
|
||||
return alwaysEnabledValueTypes;
|
||||
}
|
||||
|
||||
public List<TestFrameworkExecutor> getTestFrameworkExecutors() {
|
||||
return extensions.stream()
|
||||
.filter(e -> e instanceof TestFrameworkExecutor)
|
||||
.map(e -> (TestFrameworkExecutor) e)
|
||||
.toList();
|
||||
}
|
||||
|
||||
public List<Class<?>> getMethodValueTypes(Method method) {
|
||||
return getTestFrameworkExecutors()
|
||||
.stream()
|
||||
.flatMap(e -> e.getMethodValueTypes(method).stream()).toList();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> Supplier<T, ?> findSupplierByType(Class<T> typeClass) {
|
||||
return (Supplier<T, ?>) suppliers.stream().filter(s -> s.getValueType().equals(typeClass)).findFirst().orElse(null);
|
||||
|
||||
@ -2,6 +2,7 @@ package org.keycloak.testframework.injection;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
@ -9,7 +10,12 @@ import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import org.keycloak.testframework.TestFrameworkExecutor;
|
||||
|
||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||
import org.junit.jupiter.api.extension.InvocationInterceptor;
|
||||
import org.junit.jupiter.api.extension.ParameterContext;
|
||||
import org.junit.jupiter.api.extension.ReflectiveInvocationContext;
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public class Registry implements ExtensionContext.Store.CloseableResource {
|
||||
@ -112,8 +118,8 @@ public class Registry implements ExtensionContext.Store.CloseableResource {
|
||||
return (T) dependency.getValue();
|
||||
}
|
||||
|
||||
public void beforeEach(Object testInstance) {
|
||||
findRequestedInstances(testInstance);
|
||||
public void beforeEach(Object testInstance, Method testMethod) {
|
||||
findRequestedInstances(testInstance, testMethod);
|
||||
destroyIncompatibleInstances();
|
||||
matchDeployedInstancesWithRequestedInstances();
|
||||
deployRequestedInstances();
|
||||
@ -121,7 +127,27 @@ public class Registry implements ExtensionContext.Store.CloseableResource {
|
||||
invokeBeforeEachOnSuppliers();
|
||||
}
|
||||
|
||||
private void findRequestedInstances(Object testInstance) {
|
||||
public void intercept(InvocationInterceptor.Invocation<Void> invocation, ReflectiveInvocationContext<Method> invocationContext) throws Throwable {
|
||||
Class<?> testClass = invocationContext.getTargetClass();
|
||||
Method testMethod = invocationContext.getExecutable();
|
||||
|
||||
TestFrameworkExecutor testFrameworkExecutor = getExecutor(testMethod);
|
||||
if (testFrameworkExecutor != null) {
|
||||
testFrameworkExecutor.execute(this, testClass, testMethod);
|
||||
invocation.skip();
|
||||
} else {
|
||||
invocation.proceed();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
|
||||
Method testMethod = (Method) parameterContext.getParameter().getDeclaringExecutable();
|
||||
Class<?> parameterType = parameterContext.getParameter().getType();
|
||||
TestFrameworkExecutor testFrameworkExecutor = getExecutor(testMethod);
|
||||
return testFrameworkExecutor != null && testFrameworkExecutor.supportsParameter(testMethod, parameterType);
|
||||
}
|
||||
|
||||
private void findRequestedInstances(Object testInstance, Method testMethod) {
|
||||
List<Class<?>> alwaysEnabledValueTypes = extensions.getAlwaysEnabledValueTypes();
|
||||
for (Class<?> valueType : alwaysEnabledValueTypes) {
|
||||
RequestedInstance requestedInstance = createRequestedInstance(null, valueType);
|
||||
@ -130,6 +156,14 @@ public class Registry implements ExtensionContext.Store.CloseableResource {
|
||||
}
|
||||
}
|
||||
|
||||
List<Class<?>> methodValueTypes = extensions.getMethodValueTypes(testMethod);
|
||||
for (Class<?> valueType : methodValueTypes) {
|
||||
RequestedInstance requestedInstance = createRequestedInstance(null, valueType);
|
||||
if (requestedInstance != null) {
|
||||
requestedInstances.add(requestedInstance);
|
||||
}
|
||||
}
|
||||
|
||||
Class testClass = testInstance.getClass();
|
||||
RequestedInstance requestedServerInstance = createRequestedInstance(testClass.getAnnotations(), null);
|
||||
if (requestedServerInstance != null) {
|
||||
@ -317,6 +351,10 @@ public class Registry implements ExtensionContext.Store.CloseableResource {
|
||||
}
|
||||
}
|
||||
|
||||
private TestFrameworkExecutor getExecutor(Method testMethod) {
|
||||
return extensions.getTestFrameworkExecutors().stream().filter(e -> e.shouldExecute(testMethod)).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
private static class RequestedInstanceComparator implements Comparator<RequestedInstance> {
|
||||
|
||||
static final RequestedInstanceComparator INSTANCE = new RequestedInstanceComparator();
|
||||
|
||||
@ -1 +0,0 @@
|
||||
org.keycloak.testframework.KeycloakIntegrationTestExtension
|
||||
@ -1,5 +1,6 @@
|
||||
package org.keycloak.testframework.injection;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
import org.keycloak.testframework.config.Config;
|
||||
@ -36,7 +37,7 @@ public class RegistryTest {
|
||||
MockParentSupplier.DEFAULT_LIFECYCLE = LifeCycle.GLOBAL;
|
||||
ParentTest test = new ParentTest();
|
||||
|
||||
registry.beforeEach(test);
|
||||
runBeforeEach(test);
|
||||
MockParentValue value1 = test.parent;
|
||||
assertRunning(value1);
|
||||
|
||||
@ -45,7 +46,7 @@ public class RegistryTest {
|
||||
assertRunning(value1);
|
||||
|
||||
ParentTest test2 = new ParentTest();
|
||||
registry.beforeEach(test2);
|
||||
runBeforeEach(test2);
|
||||
MockParentValue value2 = test2.parent;
|
||||
|
||||
Assertions.assertSame(value1, value2);
|
||||
@ -59,14 +60,14 @@ public class RegistryTest {
|
||||
public void testClassLifeCycle() {
|
||||
ParentTest test = new ParentTest();
|
||||
|
||||
registry.beforeEach(test);
|
||||
runBeforeEach(test);
|
||||
MockParentValue value1 = test.parent;
|
||||
assertRunning(value1);
|
||||
|
||||
registry.afterEach();
|
||||
assertRunning(value1);
|
||||
|
||||
registry.beforeEach(test);
|
||||
runBeforeEach(test);
|
||||
MockParentValue value2 = test.parent;
|
||||
Assertions.assertSame(value1, value2);
|
||||
|
||||
@ -77,7 +78,7 @@ public class RegistryTest {
|
||||
assertClosed(value1);
|
||||
|
||||
ParentTest test2 = new ParentTest();
|
||||
registry.beforeEach(test2);
|
||||
runBeforeEach(test2);
|
||||
MockParentValue value3 = test2.parent;
|
||||
|
||||
Assertions.assertNotSame(value1, value3);
|
||||
@ -89,14 +90,14 @@ public class RegistryTest {
|
||||
|
||||
ParentTest test = new ParentTest();
|
||||
|
||||
registry.beforeEach(test);
|
||||
runBeforeEach(test);
|
||||
MockParentValue value1 = test.parent;
|
||||
assertRunning(value1);
|
||||
|
||||
registry.afterEach();
|
||||
assertClosed(value1);
|
||||
|
||||
registry.beforeEach(test);
|
||||
runBeforeEach(test);
|
||||
MockParentValue value2 = test.parent;
|
||||
Assertions.assertNotSame(value1, value2);
|
||||
}
|
||||
@ -109,14 +110,14 @@ public class RegistryTest {
|
||||
ParentAndChildTest parentAndChildTest = new ParentAndChildTest();
|
||||
MockChildValue child1 = parentAndChildTest.child;
|
||||
|
||||
registry.beforeEach(parentAndChildTest);
|
||||
runBeforeEach(parentAndChildTest);
|
||||
assertRunning(parentAndChildTest.parent, parentAndChildTest.child);
|
||||
Assertions.assertSame(parentAndChildTest.parent, parentAndChildTest.child.getParent());
|
||||
|
||||
registry.afterEach();
|
||||
assertClosed(parentAndChildTest.parent, parentAndChildTest.child);
|
||||
|
||||
registry.beforeEach(parentAndChildTest);
|
||||
runBeforeEach(parentAndChildTest);
|
||||
Assertions.assertNotSame(child1, parentAndChildTest.child);
|
||||
}
|
||||
|
||||
@ -126,7 +127,7 @@ public class RegistryTest {
|
||||
|
||||
ParentTest parentTest = new ParentTest();
|
||||
|
||||
registry.beforeEach(parentTest);
|
||||
runBeforeEach(parentTest);
|
||||
registry.afterEach();
|
||||
registry.afterAll();
|
||||
assertRunning(parentTest.parent);
|
||||
@ -134,7 +135,7 @@ public class RegistryTest {
|
||||
MockParentSupplier.DEFAULT_LIFECYCLE = LifeCycle.CLASS;
|
||||
|
||||
ParentTest parentTest2 = new ParentTest();
|
||||
registry.beforeEach(parentTest2);
|
||||
runBeforeEach(parentTest2);
|
||||
|
||||
assertRunning(parentTest2.parent);
|
||||
assertClosed(parentTest.parent);
|
||||
@ -145,13 +146,13 @@ public class RegistryTest {
|
||||
public void testRecreateIfNotCompatible() {
|
||||
ParentTest parentTest = new ParentTest();
|
||||
|
||||
registry.beforeEach(parentTest);
|
||||
runBeforeEach(parentTest);
|
||||
MockParentValue parent1 = parentTest.parent;
|
||||
registry.afterEach();
|
||||
|
||||
MockParentSupplier.COMPATIBLE = false;
|
||||
|
||||
registry.beforeEach(parentTest);
|
||||
runBeforeEach(parentTest);
|
||||
registry.afterEach();
|
||||
|
||||
MockParentValue parent2 = parentTest.parent;
|
||||
@ -191,7 +192,7 @@ public class RegistryTest {
|
||||
public void testDependencyCreatedOnDemand() {
|
||||
ChildTest childTest = new ChildTest();
|
||||
|
||||
registry.beforeEach(childTest);
|
||||
runBeforeEach(childTest);
|
||||
assertRunning(childTest.child, childTest.child.getParent());
|
||||
}
|
||||
|
||||
@ -199,7 +200,7 @@ public class RegistryTest {
|
||||
public void testDependencyRequestedBefore() {
|
||||
ParentAndChildTest test = new ParentAndChildTest();
|
||||
|
||||
registry.beforeEach(test);
|
||||
runBeforeEach(test);
|
||||
assertRunning(test.child, test.child.getParent());
|
||||
}
|
||||
|
||||
@ -207,14 +208,14 @@ public class RegistryTest {
|
||||
public void testDependencyRequestedAfter() {
|
||||
ChildAndParentTest test = new ChildAndParentTest();
|
||||
|
||||
registry.beforeEach(test);
|
||||
runBeforeEach(test);
|
||||
assertRunning(test.child, test.child.getParent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultiplRef() {
|
||||
MultipleRefTest refTest = new MultipleRefTest();
|
||||
registry.beforeEach(refTest);
|
||||
runBeforeEach(refTest);
|
||||
|
||||
MockParentValue def1 = refTest.def;
|
||||
MockParentValue a1 = refTest.a;
|
||||
@ -228,7 +229,7 @@ public class RegistryTest {
|
||||
|
||||
registry.afterEach();
|
||||
|
||||
registry.beforeEach(refTest);
|
||||
runBeforeEach(refTest);
|
||||
assertRunning(refTest.def, refTest.a2, refTest.b);
|
||||
|
||||
Assertions.assertSame(def1, refTest.def);
|
||||
@ -244,7 +245,7 @@ public class RegistryTest {
|
||||
@Test
|
||||
public void testRealmRef() {
|
||||
RealmRefTest test = new RealmRefTest();
|
||||
registry.beforeEach(test);
|
||||
runBeforeEach(test);
|
||||
|
||||
assertRunning(test.childABC, test.childABC.getParent(), test.child123, test.parent123);
|
||||
Assertions.assertNotSame(test.childABC.getParent(), test.parent123);
|
||||
@ -254,7 +255,7 @@ public class RegistryTest {
|
||||
@Test
|
||||
public void testConfigurableSupplier() {
|
||||
ParentTest parentTest = new ParentTest();
|
||||
registry.beforeEach(parentTest);
|
||||
runBeforeEach(parentTest);
|
||||
|
||||
Assertions.assertNull(parentTest.parent.getStringOption());
|
||||
Assertions.assertTrue(parentTest.parent.isBooleanOption());
|
||||
@ -267,7 +268,7 @@ public class RegistryTest {
|
||||
Extensions.reset();
|
||||
registry = new Registry();
|
||||
parentTest = new ParentTest();
|
||||
registry.beforeEach(parentTest);
|
||||
runBeforeEach(parentTest);
|
||||
|
||||
Assertions.assertEquals("some string", parentTest.parent.getStringOption());
|
||||
Assertions.assertFalse(parentTest.parent.isBooleanOption());
|
||||
@ -282,7 +283,7 @@ public class RegistryTest {
|
||||
public void testIncompatibleParent() {
|
||||
MockParentSupplier.COMPATIBLE = false;
|
||||
RealmIncompatibleParentTest test = new RealmIncompatibleParentTest();
|
||||
registry.beforeEach(test);
|
||||
runBeforeEach(test);
|
||||
|
||||
MockParentValue parent1 = test.parent;
|
||||
MockChildValue child1 = test.child;
|
||||
@ -292,7 +293,7 @@ public class RegistryTest {
|
||||
|
||||
registry.afterEach();
|
||||
|
||||
registry.beforeEach(test);
|
||||
runBeforeEach(test);
|
||||
|
||||
Assertions.assertNotNull(test.parent);
|
||||
Assertions.assertNotEquals(parent1, test.parent);
|
||||
@ -300,6 +301,15 @@ public class RegistryTest {
|
||||
Assertions.assertNotEquals(child1, test.child);
|
||||
}
|
||||
|
||||
private <T extends AbstractTest> void runBeforeEach(T testInstance) {
|
||||
try {
|
||||
Method testMethod = testInstance.getClass().getMethod("test");
|
||||
registry.beforeEach(testInstance, testMethod);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void assertRunning(Object... values) {
|
||||
MatcherAssert.assertThat(MockInstances.INSTANCES, Matchers.hasItems(values));
|
||||
MatcherAssert.assertThat(MockInstances.INSTANCES, Matchers.hasSize(values.length));
|
||||
@ -310,7 +320,13 @@ public class RegistryTest {
|
||||
MatcherAssert.assertThat(MockInstances.CLOSED_INSTANCES, Matchers.hasSize(values.length));
|
||||
}
|
||||
|
||||
public static final class ParentAndChildTest {
|
||||
public static abstract class AbstractTest {
|
||||
@Test
|
||||
public void test() {
|
||||
}
|
||||
}
|
||||
|
||||
public static final class ParentAndChildTest extends AbstractTest {
|
||||
@MockParentAnnotation
|
||||
MockParentValue parent;
|
||||
|
||||
@ -318,17 +334,17 @@ public class RegistryTest {
|
||||
MockChildValue child;
|
||||
}
|
||||
|
||||
public static final class ParentTest {
|
||||
public static final class ParentTest extends AbstractTest {
|
||||
@MockParentAnnotation
|
||||
MockParentValue parent;
|
||||
}
|
||||
|
||||
public static final class ChildTest {
|
||||
public static final class ChildTest extends AbstractTest {
|
||||
@MockChildAnnotation
|
||||
MockChildValue child;
|
||||
}
|
||||
|
||||
public static final class ChildAndParentTest {
|
||||
public static final class ChildAndParentTest extends AbstractTest {
|
||||
@MockChildAnnotation
|
||||
MockChildValue child;
|
||||
|
||||
@ -336,7 +352,7 @@ public class RegistryTest {
|
||||
MockParentValue parent;
|
||||
}
|
||||
|
||||
public static final class MultipleRefTest {
|
||||
public static final class MultipleRefTest extends AbstractTest {
|
||||
@MockParentAnnotation()
|
||||
MockParentValue def;
|
||||
|
||||
@ -350,7 +366,7 @@ public class RegistryTest {
|
||||
MockParentValue b;
|
||||
}
|
||||
|
||||
public static final class RealmRefTest {
|
||||
public static final class RealmRefTest extends AbstractTest {
|
||||
@MockParentAnnotation(ref = "123")
|
||||
MockParentValue parent123;
|
||||
|
||||
@ -361,7 +377,7 @@ public class RegistryTest {
|
||||
MockChildValue childABC;
|
||||
}
|
||||
|
||||
public static final class RealmIncompatibleParentTest {
|
||||
public static final class RealmIncompatibleParentTest extends AbstractTest {
|
||||
|
||||
@MockChildAnnotation
|
||||
MockChildValue child;
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
package org.keycloak.test.examples;
|
||||
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.testframework.annotations.InjectRealm;
|
||||
import org.keycloak.testframework.annotations.KeycloakIntegrationTest;
|
||||
import org.keycloak.testframework.realm.ManagedRealm;
|
||||
import org.keycloak.testframework.remote.annotations.TestOnServer;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@KeycloakIntegrationTest
|
||||
public class RunTestOnServerTest {
|
||||
|
||||
@InjectRealm
|
||||
ManagedRealm realm;
|
||||
|
||||
@TestOnServer
|
||||
public void test(KeycloakSession session) throws Throwable {
|
||||
Assertions.assertNotNull(session);
|
||||
Assertions.assertNull(realm);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test2() {
|
||||
Assertions.assertNotNull(realm);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,2 +1 @@
|
||||
junit.jupiter.extensions.autodetection.enabled=true
|
||||
junit.jupiter.testclass.order.default=org.keycloak.testframework.ServerConfigClassOrderer
|
||||
@ -1,14 +1,22 @@
|
||||
package org.keycloak.testframework.remote;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.testframework.TestFrameworkExecutor;
|
||||
import org.keycloak.testframework.TestFrameworkExtension;
|
||||
import org.keycloak.testframework.injection.Registry;
|
||||
import org.keycloak.testframework.injection.Supplier;
|
||||
import org.keycloak.testframework.remote.annotations.TestOnServer;
|
||||
import org.keycloak.testframework.remote.runonserver.RunOnServerClient;
|
||||
import org.keycloak.testframework.remote.runonserver.RunOnServerSupplier;
|
||||
import org.keycloak.testframework.remote.runonserver.RunTestOnServer;
|
||||
import org.keycloak.testframework.remote.runonserver.TestClassServerSupplier;
|
||||
import org.keycloak.testframework.remote.timeoffset.TimeOffsetSupplier;
|
||||
|
||||
public class RemoteTestFrameworkExtension implements TestFrameworkExtension {
|
||||
public class RemoteTestFrameworkExtension implements TestFrameworkExtension, TestFrameworkExecutor {
|
||||
@Override
|
||||
public List<Supplier<?, ?>> suppliers() {
|
||||
return List.of(
|
||||
@ -23,4 +31,32 @@ public class RemoteTestFrameworkExtension implements TestFrameworkExtension {
|
||||
public List<Class<?>> alwaysEnabledValueTypes() {
|
||||
return List.of(RemoteProviders.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Class<?>> getMethodValueTypes(Method method) {
|
||||
return isTestOnServer(method) ? List.of(RunOnServerClient.class) : Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsParameter(Method method, Class<?> parameterType) {
|
||||
return isTestOnServer(method) && parameterType.equals(KeycloakSession.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldExecute(Method testMethod) {
|
||||
return isTestOnServer(testMethod);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Registry registry, Class<?> testClass, Method testMethod) {
|
||||
RunOnServerClient value = (RunOnServerClient) registry.getDeployedInstances().stream().filter(i -> i.getRequestedValueType() != null && i.getRequestedValueType().equals(RunOnServerClient.class)).findFirst().get().getValue();
|
||||
|
||||
RunTestOnServer runTestOnServer = new RunTestOnServer(testClass.getName(), testMethod.getName());
|
||||
value.run(runTestOnServer);
|
||||
}
|
||||
|
||||
private boolean isTestOnServer(Method method) {
|
||||
return method.isAnnotationPresent(TestOnServer.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
package org.keycloak.testframework.remote.annotations;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
@Test
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface TestOnServer {
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
package org.keycloak.testframework.remote.runonserver;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.keycloak.common.VerificationException;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.testframework.remote.providers.runonserver.RunOnServer;
|
||||
|
||||
public class RunTestOnServer implements RunOnServer {
|
||||
|
||||
private final String testClass;
|
||||
private final String testMethod;
|
||||
|
||||
public RunTestOnServer(String testClass, String testMethod) {
|
||||
this.testClass = testClass;
|
||||
this.testMethod = testMethod;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(KeycloakSession session) throws IOException, VerificationException {
|
||||
try {
|
||||
Class<?> clazz = this.getClass().getClassLoader().loadClass(testClass);
|
||||
Object test = clazz.getDeclaredConstructor().newInstance();
|
||||
Method method = clazz.getDeclaredMethod(testMethod, KeycloakSession.class);
|
||||
method.invoke(test, session);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user