Testsuite PoC - Injection framework support for multiple instances (#31293)
* Testsuite PoC - Injection framework support for multiple instances Closes #30613 Signed-off-by: Simon Vacek <simonvacky@email.cz> * Add unit tests for multiple instances Signed-off-by: stianst <stianst@gmail.com> * Remove check for ref redefinitions Signed-off-by: Simon Vacek <simonvacky@email.cz> --------- Signed-off-by: Simon Vacek <simonvacky@email.cz> Signed-off-by: stianst <stianst@gmail.com> Co-authored-by: stianst <stianst@gmail.com>
This commit is contained in:
parent
b5597c6293
commit
6de396d537
16 changed files with 156 additions and 21 deletions
|
@ -28,17 +28,17 @@ public class GlobalManagedResourcesTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreatedRealm() {
|
public void testCreatedRealm() {
|
||||||
Assertions.assertEquals(DefaultRealmConfig.class.getSimpleName(), realmResource.toRepresentation().getRealm());
|
Assertions.assertEquals("default", realmResource.toRepresentation().getRealm());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreatedClient() {
|
public void testCreatedClient() {
|
||||||
Assertions.assertEquals(DefaultClientConfig.class.getSimpleName(), clientResource.toRepresentation().getClientId());
|
Assertions.assertEquals("default", clientResource.toRepresentation().getClientId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreatedUser() {
|
public void testCreatedUser() {
|
||||||
Assertions.assertEquals(DefaultUserConfig.class.getSimpleName().toLowerCase(), userResource.toRepresentation().getUsername());
|
Assertions.assertEquals("default", userResource.toRepresentation().getUsername());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,14 +23,14 @@ public class ManagedResources2Test {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreatedRealm() {
|
public void testCreatedRealm() {
|
||||||
Assertions.assertEquals(ManagedResources2Test.class.getSimpleName(), realmResource.toRepresentation().getRealm());
|
Assertions.assertEquals("default", realmResource.toRepresentation().getRealm());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreatedClient() {
|
public void testCreatedClient() {
|
||||||
Assertions.assertEquals(ManagedResources2Test.class.getSimpleName(), clientResource.toRepresentation().getClientId());
|
Assertions.assertEquals("default", clientResource.toRepresentation().getClientId());
|
||||||
|
|
||||||
List<ClientRepresentation> clients = realmResource.clients().findByClientId(ManagedResources2Test.class.getSimpleName());
|
List<ClientRepresentation> clients = realmResource.clients().findByClientId("default");
|
||||||
Assertions.assertEquals(1, clients.size());
|
Assertions.assertEquals(1, clients.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,20 +28,20 @@ public class ManagedResourcesTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreatedRealm() {
|
public void testCreatedRealm() {
|
||||||
Assertions.assertEquals(ManagedResourcesTest.class.getSimpleName(), realmResource.toRepresentation().getRealm());
|
Assertions.assertEquals("default", realmResource.toRepresentation().getRealm());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreatedClient() {
|
public void testCreatedClient() {
|
||||||
Assertions.assertEquals(ManagedResourcesTest.class.getSimpleName(), clientResource.toRepresentation().getClientId());
|
Assertions.assertEquals("default", clientResource.toRepresentation().getClientId());
|
||||||
|
|
||||||
List<ClientRepresentation> clients = realmResource.clients().findByClientId(ManagedResourcesTest.class.getSimpleName());
|
List<ClientRepresentation> clients = realmResource.clients().findByClientId("default");
|
||||||
Assertions.assertEquals(1, clients.size());
|
Assertions.assertEquals(1, clients.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreatedUser() {
|
public void testCreatedUser() {
|
||||||
Assertions.assertEquals(ManagedResourcesTest.class.getSimpleName().toLowerCase(), userResource.toRepresentation().getUsername());
|
Assertions.assertEquals("default", userResource.toRepresentation().getUsername());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
package org.keycloak.test.examples;
|
||||||
|
|
||||||
|
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.representations.idm.RealmRepresentation;
|
||||||
|
import org.keycloak.representations.idm.UserRepresentation;
|
||||||
|
import org.keycloak.test.framework.annotations.KeycloakIntegrationTest;
|
||||||
|
import org.keycloak.test.framework.annotations.TestClient;
|
||||||
|
import org.keycloak.test.framework.annotations.TestRealm;
|
||||||
|
import org.keycloak.test.framework.realm.RealmConfig;
|
||||||
|
|
||||||
|
@KeycloakIntegrationTest
|
||||||
|
public class MultipleInstancesTest {
|
||||||
|
|
||||||
|
@TestRealm
|
||||||
|
RealmResource realm1;
|
||||||
|
|
||||||
|
@TestRealm
|
||||||
|
RealmResource realm2;
|
||||||
|
|
||||||
|
@TestRealm(ref = "another", config = CustomRealmConfig.class)
|
||||||
|
RealmResource realm3;
|
||||||
|
|
||||||
|
@TestClient(ref = "client1")
|
||||||
|
ClientResource client;
|
||||||
|
|
||||||
|
@TestClient
|
||||||
|
ClientResource client2;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMultipleInstances() {
|
||||||
|
Assertions.assertEquals("default", realm1.toRepresentation().getRealm());
|
||||||
|
Assertions.assertEquals("default", realm2.toRepresentation().getRealm());
|
||||||
|
Assertions.assertEquals(realm1, realm2);
|
||||||
|
|
||||||
|
Assertions.assertEquals("another", realm3.toRepresentation().getRealm());
|
||||||
|
|
||||||
|
Assertions.assertEquals("client1", client.toRepresentation().getClientId());
|
||||||
|
Assertions.assertEquals("default", client2.toRepresentation().getClientId());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class CustomRealmConfig implements RealmConfig {
|
||||||
|
@Override
|
||||||
|
public RealmRepresentation getRepresentation() {
|
||||||
|
return new RealmRepresentation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -15,6 +15,8 @@ public @interface TestClient {
|
||||||
|
|
||||||
Class<? extends ClientConfig> config() default DefaultClientConfig.class;
|
Class<? extends ClientConfig> config() default DefaultClientConfig.class;
|
||||||
|
|
||||||
|
String ref() default "default";
|
||||||
|
|
||||||
LifeCycle lifecycle() default LifeCycle.CLASS;
|
LifeCycle lifecycle() default LifeCycle.CLASS;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,4 +17,5 @@ public @interface TestRealm {
|
||||||
|
|
||||||
LifeCycle lifecycle() default LifeCycle.CLASS;
|
LifeCycle lifecycle() default LifeCycle.CLASS;
|
||||||
|
|
||||||
|
String ref() default "default";
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,4 +17,5 @@ public @interface TestUser {
|
||||||
|
|
||||||
LifeCycle lifecycle() default LifeCycle.CLASS;
|
LifeCycle lifecycle() default LifeCycle.CLASS;
|
||||||
|
|
||||||
|
String ref() default "default";
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ public class InstanceContext<T, A extends Annotation> {
|
||||||
private T value;
|
private T value;
|
||||||
private Class<? extends T> requestedValueType;
|
private Class<? extends T> requestedValueType;
|
||||||
private LifeCycle lifeCycle;
|
private LifeCycle lifeCycle;
|
||||||
|
private final String ref;
|
||||||
private final Map<String, Object> notes = new HashMap<>();
|
private final Map<String, Object> notes = new HashMap<>();
|
||||||
|
|
||||||
public InstanceContext(Registry registry, Supplier<T, A> supplier, A annotation, Class<? extends T> requestedValueType) {
|
public InstanceContext(Registry registry, Supplier<T, A> supplier, A annotation, Class<? extends T> requestedValueType) {
|
||||||
|
@ -23,6 +24,7 @@ public class InstanceContext<T, A extends Annotation> {
|
||||||
this.annotation = annotation;
|
this.annotation = annotation;
|
||||||
this.requestedValueType = requestedValueType;
|
this.requestedValueType = requestedValueType;
|
||||||
this.lifeCycle = supplier.getLifeCycle(annotation);
|
this.lifeCycle = supplier.getLifeCycle(annotation);
|
||||||
|
this.ref = supplier.getRef(annotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <D> D getDependency(Class<D> typeClazz) {
|
public <D> D getDependency(Class<D> typeClazz) {
|
||||||
|
@ -53,6 +55,10 @@ public class InstanceContext<T, A extends Annotation> {
|
||||||
return lifeCycle;
|
return lifeCycle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getRef() {
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
public A getAnnotation() {
|
public A getAnnotation() {
|
||||||
return annotation;
|
return annotation;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ import java.util.Optional;
|
||||||
import java.util.ServiceLoader;
|
import java.util.ServiceLoader;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
public class Registry {
|
public class Registry {
|
||||||
|
@ -146,6 +147,7 @@ public class Registry {
|
||||||
while (!requestedInstances.isEmpty()) {
|
while (!requestedInstances.isEmpty()) {
|
||||||
RequestedInstance requestedInstance = requestedInstances.remove(0);
|
RequestedInstance requestedInstance = requestedInstances.remove(0);
|
||||||
|
|
||||||
|
if (getDeployedInstance(requestedInstance) == null) {
|
||||||
InstanceContext instance = new InstanceContext(this, requestedInstance.getSupplier(), requestedInstance.getAnnotation(), requestedInstance.getValueType());
|
InstanceContext instance = new InstanceContext(this, requestedInstance.getSupplier(), requestedInstance.getAnnotation(), requestedInstance.getValueType());
|
||||||
instance.setValue(requestedInstance.getSupplier().getValue(instance));
|
instance.setValue(requestedInstance.getSupplier().getValue(instance));
|
||||||
deployedInstances.add(instance);
|
deployedInstances.add(instance);
|
||||||
|
@ -156,6 +158,7 @@ public class Registry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void injectFields(Object testInstance) {
|
private void injectFields(Object testInstance) {
|
||||||
for (Field f : testInstance.getClass().getDeclaredFields()) {
|
for (Field f : testInstance.getClass().getDeclaredFields()) {
|
||||||
|
@ -205,8 +208,10 @@ public class Registry {
|
||||||
private InstanceContext<?, ?> getDeployedInstance(Class<?> valueType, Annotation[] annotations) {
|
private InstanceContext<?, ?> getDeployedInstance(Class<?> valueType, Annotation[] annotations) {
|
||||||
for (Annotation a : annotations) {
|
for (Annotation a : annotations) {
|
||||||
for (InstanceContext<?, ?> i : deployedInstances) {
|
for (InstanceContext<?, ?> i : deployedInstances) {
|
||||||
Supplier<?, ?> supplier = i.getSupplier();
|
Supplier supplier = i.getSupplier();
|
||||||
if (supplier.getAnnotationClass().equals(a.annotationType()) && valueType.isAssignableFrom(i.getValue().getClass())) {
|
if (supplier.getAnnotationClass().equals(a.annotationType())
|
||||||
|
&& valueType.isAssignableFrom(i.getValue().getClass())
|
||||||
|
&& supplier.getRef(a).equals(i.getRef()) ) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -229,8 +234,13 @@ public class Registry {
|
||||||
}
|
}
|
||||||
|
|
||||||
private InstanceContext getDeployedInstance(RequestedInstance requestedInstance) {
|
private InstanceContext getDeployedInstance(RequestedInstance requestedInstance) {
|
||||||
|
String requestedRef = requestedInstance.getRef();
|
||||||
Class requestedValueType = requestedInstance.getValueType();
|
Class requestedValueType = requestedInstance.getValueType();
|
||||||
for (InstanceContext<?, ?> i : deployedInstances) {
|
for (InstanceContext<?, ?> i : deployedInstances) {
|
||||||
|
if(!i.getRef().equals(requestedRef)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (requestedValueType != null) {
|
if (requestedValueType != null) {
|
||||||
if (requestedValueType.isAssignableFrom(i.getValue().getClass())) {
|
if (requestedValueType.isAssignableFrom(i.getValue().getClass())) {
|
||||||
return i;
|
return i;
|
||||||
|
|
|
@ -8,12 +8,14 @@ public class RequestedInstance<T, A extends Annotation> {
|
||||||
private final A annotation;
|
private final A annotation;
|
||||||
private final Class<? extends T> valueType;
|
private final Class<? extends T> valueType;
|
||||||
private final LifeCycle lifeCycle;
|
private final LifeCycle lifeCycle;
|
||||||
|
private final String ref;
|
||||||
|
|
||||||
public RequestedInstance(Supplier<T, A> supplier, A annotation, Class<? extends T> valueType) {
|
public RequestedInstance(Supplier<T, A> supplier, A annotation, Class<? extends T> valueType) {
|
||||||
this.supplier = supplier;
|
this.supplier = supplier;
|
||||||
this.annotation = annotation;
|
this.annotation = annotation;
|
||||||
this.valueType = valueType;
|
this.valueType = valueType;
|
||||||
this.lifeCycle = supplier.getLifeCycle(annotation);
|
this.lifeCycle = supplier.getLifeCycle(annotation);
|
||||||
|
this.ref = supplier.getRef(annotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Supplier<T, A> getSupplier() {
|
public Supplier<T, A> getSupplier() {
|
||||||
|
@ -31,4 +33,8 @@ public class RequestedInstance<T, A extends Annotation> {
|
||||||
public LifeCycle getLifeCycle() {
|
public LifeCycle getLifeCycle() {
|
||||||
return lifeCycle;
|
return lifeCycle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getRef() {
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,20 @@ public interface Supplier<T, S extends Annotation> {
|
||||||
return getDefaultLifecycle();
|
return getDefaultLifecycle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default String getRef(S annotation) {
|
||||||
|
if (annotation != null) {
|
||||||
|
Optional<Method> ref = Arrays.stream(annotation.annotationType().getMethods()).filter(m -> m.getName().equals("ref")).findFirst();
|
||||||
|
if (ref.isPresent()) {
|
||||||
|
try {
|
||||||
|
return (String) ref.get().invoke(annotation);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
default LifeCycle getDefaultLifecycle() {
|
default LifeCycle getDefaultLifecycle() {
|
||||||
return LifeCycle.CLASS;
|
return LifeCycle.CLASS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ public class ClientSupplier implements Supplier<ClientResource, TestClient> {
|
||||||
ClientRepresentation clientRepresentation = config.getRepresentation();
|
ClientRepresentation clientRepresentation = config.getRepresentation();
|
||||||
|
|
||||||
if (clientRepresentation.getClientId() == null) {
|
if (clientRepresentation.getClientId() == null) {
|
||||||
String clientId = instanceContext.getLifeCycle().equals(LifeCycle.GLOBAL) ? config.getClass().getSimpleName() : instanceContext.getRegistry().getCurrentContext().getRequiredTestClass().getSimpleName();
|
String clientId = instanceContext.getRef();
|
||||||
clientRepresentation.setClientId(clientId);
|
clientRepresentation.setClientId(clientId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ public class RealmSupplier implements Supplier<RealmResource, TestRealm> {
|
||||||
RealmRepresentation realmRepresentation = config.getRepresentation();
|
RealmRepresentation realmRepresentation = config.getRepresentation();
|
||||||
|
|
||||||
if (realmRepresentation.getRealm() == null) {
|
if (realmRepresentation.getRealm() == null) {
|
||||||
String realmName = instanceContext.getLifeCycle().equals(LifeCycle.GLOBAL) ? config.getClass().getSimpleName() : instanceContext.getRegistry().getCurrentContext().getRequiredTestClass().getSimpleName();
|
String realmName = instanceContext.getRef();
|
||||||
realmRepresentation.setRealm(realmName);
|
realmRepresentation.setRealm(realmName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ public class UserSupplier implements Supplier<UserResource, TestUser> {
|
||||||
UserRepresentation userRepresentation = config.getRepresentation();
|
UserRepresentation userRepresentation = config.getRepresentation();
|
||||||
|
|
||||||
if (userRepresentation.getUsername() == null) {
|
if (userRepresentation.getUsername() == null) {
|
||||||
String username = instanceContext.getLifeCycle().equals(LifeCycle.GLOBAL) ? config.getClass().getSimpleName() : instanceContext.getRegistry().getCurrentContext().getRequiredTestClass().getSimpleName();
|
String username = instanceContext.getRef();
|
||||||
userRepresentation.setUsername(username);
|
userRepresentation.setUsername(username);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -208,6 +208,35 @@ public class RegistryTest {
|
||||||
assertRunning(test.child, test.child.getParent());
|
assertRunning(test.child, test.child.getParent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMultiplRef() {
|
||||||
|
MultipleRefTest refTest = new MultipleRefTest();
|
||||||
|
registry.beforeEach(refTest);
|
||||||
|
|
||||||
|
MockParentValue def1 = refTest.def;
|
||||||
|
MockParentValue a1 = refTest.a;
|
||||||
|
|
||||||
|
Assertions.assertNotSame(refTest.def, refTest.a);
|
||||||
|
Assertions.assertNotSame(refTest.def, refTest.b);
|
||||||
|
Assertions.assertNotSame(refTest.a, refTest.b);
|
||||||
|
|
||||||
|
assertRunning(refTest.def, refTest.a, refTest.b);
|
||||||
|
|
||||||
|
registry.afterEach();
|
||||||
|
|
||||||
|
registry.beforeEach(refTest);
|
||||||
|
assertRunning(refTest.def, refTest.a, refTest.b);
|
||||||
|
|
||||||
|
Assertions.assertSame(def1, refTest.def);
|
||||||
|
Assertions.assertSame(a1, refTest.a);
|
||||||
|
|
||||||
|
registry.afterEach();
|
||||||
|
assertRunning(refTest.def, refTest.a, refTest.b);
|
||||||
|
|
||||||
|
registry.afterAll();
|
||||||
|
assertClosed(refTest.def, refTest.a, refTest.b);
|
||||||
|
}
|
||||||
|
|
||||||
public static void assertRunning(Object... values) {
|
public static void assertRunning(Object... values) {
|
||||||
MatcherAssert.assertThat(MockInstances.INSTANCES, Matchers.hasItems(values));
|
MatcherAssert.assertThat(MockInstances.INSTANCES, Matchers.hasItems(values));
|
||||||
MatcherAssert.assertThat(MockInstances.INSTANCES, Matchers.hasSize(values.length));
|
MatcherAssert.assertThat(MockInstances.INSTANCES, Matchers.hasSize(values.length));
|
||||||
|
@ -243,4 +272,15 @@ public class RegistryTest {
|
||||||
@MockParentAnnotation
|
@MockParentAnnotation
|
||||||
MockParentValue parent;
|
MockParentValue parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final class MultipleRefTest {
|
||||||
|
@MockParentAnnotation()
|
||||||
|
MockParentValue def;
|
||||||
|
|
||||||
|
@MockParentAnnotation(ref = "a")
|
||||||
|
MockParentValue a;
|
||||||
|
|
||||||
|
@MockParentAnnotation(ref = "b")
|
||||||
|
MockParentValue b;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,4 +8,7 @@ import java.lang.annotation.Target;
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target(ElementType.FIELD)
|
@Target(ElementType.FIELD)
|
||||||
public @interface MockParentAnnotation {
|
public @interface MockParentAnnotation {
|
||||||
|
|
||||||
|
String ref() default "";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue