test: implement unit tests for RabbitMQ RPC endpoint
This commit is contained in:
@@ -62,6 +62,8 @@ dependencyManagement {
|
||||
}
|
||||
}
|
||||
|
||||
// https://javadoc.io/doc/org.mockito/mockito-core/latest/org.mockito/org/mockito/Mockito.html#0.3
|
||||
val mockitoAgent = configurations.create("mockitoAgent")
|
||||
dependencies {
|
||||
implementation("org.springframework.boot:spring-boot-starter-validation")
|
||||
implementation("org.springframework.boot:spring-boot-starter-webflux")
|
||||
@@ -79,9 +81,11 @@ dependencies {
|
||||
testImplementation("io.projectreactor:reactor-test")
|
||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||
testImplementation("com.squareup.okhttp3:mockwebserver:4.12.0")
|
||||
mockitoAgent("org.mockito:mockito-core") { isTransitive = false }
|
||||
}
|
||||
|
||||
tasks.withType<Test> {
|
||||
jvmArgs("-javaagent:${mockitoAgent.asPath}")
|
||||
useJUnitPlatform()
|
||||
// generate jacoco test report
|
||||
finalizedBy("jacocoTestReport")
|
||||
|
||||
@@ -14,7 +14,6 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
/**
|
||||
* Abstract class for endpoint of auth-service over RabbitMQ.
|
||||
@@ -34,7 +33,7 @@ public abstract class AbstractEndpoint implements AutoCloseable {
|
||||
* Initialize this abstract class.
|
||||
*/
|
||||
public AbstractEndpoint(
|
||||
@RequestParam final CleverMicroAmqpClient client,
|
||||
final CleverMicroAmqpClient client,
|
||||
final ObjectMapper objectMapper,
|
||||
final String routingKey
|
||||
) throws IOException {
|
||||
@@ -51,7 +50,14 @@ public abstract class AbstractEndpoint implements AutoCloseable {
|
||||
);
|
||||
this.handlerTag = client.getHandlerManager().registerHandler(
|
||||
this.queueName, "", 1,
|
||||
ctx -> new Thread(() -> {
|
||||
ctx -> new Thread(() -> handleRabbitMessage(ctx)).start(),
|
||||
tag -> log.info("Endpoint canceled for queue {}: handlerTag={}",
|
||||
this.queueName, tag)
|
||||
);
|
||||
}
|
||||
|
||||
// VisibleForTesting
|
||||
void handleRabbitMessage(final HandlerContext ctx) {
|
||||
try {
|
||||
final var req = parseRequest(ctx);
|
||||
if (req == null) {
|
||||
@@ -71,13 +77,11 @@ public abstract class AbstractEndpoint implements AutoCloseable {
|
||||
"Error when handling the request", t);
|
||||
reply(ctx, resp);
|
||||
}
|
||||
}).start(),
|
||||
tag -> log.info("Endpoint canceled for queue {}: handlerTag={}",
|
||||
this.queueName, tag)
|
||||
);
|
||||
}
|
||||
|
||||
private EndpointRequest parseRequest(final HandlerContext ctx) {
|
||||
|
||||
// VisibleForTesting
|
||||
EndpointRequest parseRequest(final HandlerContext ctx) {
|
||||
InputStream reqStream = null;
|
||||
if (ctx.getMessageBodySingleStream().isPresent()) {
|
||||
reqStream = ctx.getMessageBodySingleStream().get();
|
||||
@@ -112,7 +116,7 @@ public abstract class AbstractEndpoint implements AutoCloseable {
|
||||
/**
|
||||
* Try to reply. Refill counter if error.
|
||||
*/
|
||||
protected final void reply(final HandlerContext ctx, final Object response) {
|
||||
protected void reply(final HandlerContext ctx, final Object response) {
|
||||
final byte[] bytes;
|
||||
try {
|
||||
bytes = this.objectMapper.writerWithDefaultPrettyPrinter()
|
||||
|
||||
+64
-70
@@ -6,14 +6,15 @@ import com.cleverthis.authservice.dto.keycloakadmin.KeycloakInvitationRequest;
|
||||
import com.cleverthis.authservice.exception.RegistrationException;
|
||||
import com.cleverthis.authservice.exception.ServiceUnavailableException;
|
||||
import com.cleverthis.authservice.exception.UserAlreadyExistsException;
|
||||
import jakarta.ws.rs.ClientErrorException;
|
||||
import jakarta.ws.rs.NotFoundException;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.function.Consumer;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.keycloak.admin.client.Keycloak;
|
||||
import org.keycloak.representations.idm.ClientRepresentation;
|
||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||
import org.keycloak.representations.idm.GroupRepresentation;
|
||||
import org.keycloak.representations.idm.MemberRepresentation;
|
||||
@@ -21,6 +22,7 @@ import org.keycloak.representations.idm.OrganizationRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.springframework.stereotype.Service;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.core.publisher.MonoSink;
|
||||
|
||||
/**
|
||||
* Service to interact with Keycloak Admin API.
|
||||
@@ -46,39 +48,6 @@ public class KeycloakAdminReactiveClient {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetches the internal UUID of a Keycloak client given its public clientId.
|
||||
*
|
||||
* @param publicClientId The human-readable client_id (e.g., "cleverswarm-client").
|
||||
* @return Mono emitting the internal UUID string.
|
||||
*/
|
||||
public Mono<String> getClientInternalId(String publicClientId) {
|
||||
log.debug("Fetching internal ID for client: {}", publicClientId);
|
||||
|
||||
return Mono.just(this.keycloak.realm(this.realm)
|
||||
.clients().findByClientId(publicClientId))
|
||||
.flatMap(result -> {
|
||||
if (result.isEmpty()) {
|
||||
log.warn("Client id '{}' not found in Keycloak", publicClientId);
|
||||
return Mono.error(new ServiceUnavailableException(
|
||||
"Client not found in Keycloak: " + publicClientId));
|
||||
} else {
|
||||
return Mono.just(result.getFirst());
|
||||
}
|
||||
})
|
||||
.map(ClientRepresentation::getId)
|
||||
.doOnSuccess(id -> log.debug("Found internal ID '{}' for client '{}'", id,
|
||||
publicClientId))
|
||||
.onErrorMap(t -> {
|
||||
log.error("Failed to get client '{}'",
|
||||
publicClientId, t);
|
||||
return new ServiceUnavailableException(
|
||||
"Could not fetch client details from Keycloak, clientPublicId="
|
||||
+ publicClientId, t);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new organization in Keycloak.
|
||||
*
|
||||
@@ -125,8 +94,15 @@ public class KeycloakAdminReactiveClient {
|
||||
* @return A Mono emitting the representation of the found organization.
|
||||
*/
|
||||
public Mono<OrganizationRepresentation> getOrganizationById(String orgId) {
|
||||
return Mono.just(this.keycloak.realm(this.realm)
|
||||
return Mono.create(sink -> {
|
||||
try {
|
||||
sink.success(this.keycloak.realm(this.realm)
|
||||
.organizations().get(orgId).toRepresentation());
|
||||
} catch (final NotFoundException ex) {
|
||||
sink.error(new NoSuchElementException(
|
||||
"Organization with id " + orgId + " not exists", ex));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -153,8 +129,6 @@ public class KeycloakAdminReactiveClient {
|
||||
} else {
|
||||
sink.success();
|
||||
}
|
||||
} catch (final Throwable t) {
|
||||
sink.error(t);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -179,8 +153,6 @@ public class KeycloakAdminReactiveClient {
|
||||
} else {
|
||||
sink.success();
|
||||
}
|
||||
} catch (final Throwable t) {
|
||||
sink.error(t);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -211,8 +183,6 @@ public class KeycloakAdminReactiveClient {
|
||||
} else {
|
||||
sink.success();
|
||||
}
|
||||
} catch (final Throwable t) {
|
||||
sink.error(t);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -224,9 +194,16 @@ public class KeycloakAdminReactiveClient {
|
||||
* @return A Mono emitting a List of user representations for the members.
|
||||
*/
|
||||
public Mono<List<MemberRepresentation>> getOrganizationMembers(String orgId) {
|
||||
return Mono.just(this.keycloak.realm(this.realm)
|
||||
return Mono.create(sink -> {
|
||||
try {
|
||||
sink.success(this.keycloak.realm(this.realm)
|
||||
.organizations().get(orgId)
|
||||
.members().list(null, Integer.MAX_VALUE));
|
||||
} catch (final NotFoundException ex) {
|
||||
sink.error(new NoSuchElementException(
|
||||
"Organization with id " + orgId + " not exists", ex));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -253,8 +230,6 @@ public class KeycloakAdminReactiveClient {
|
||||
} else {
|
||||
sink.success();
|
||||
}
|
||||
} catch (final Throwable t) {
|
||||
sink.error(t);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -281,8 +256,6 @@ public class KeycloakAdminReactiveClient {
|
||||
} else {
|
||||
sink.success();
|
||||
}
|
||||
} catch (final Throwable t) {
|
||||
sink.error(t);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -310,8 +283,6 @@ public class KeycloakAdminReactiveClient {
|
||||
} else {
|
||||
sink.success();
|
||||
}
|
||||
} catch (final Throwable t) {
|
||||
sink.error(t);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -323,8 +294,12 @@ public class KeycloakAdminReactiveClient {
|
||||
* @return A Mono emitting the group representation.
|
||||
*/
|
||||
public Mono<GroupRepresentation> getGroupById(String groupId) {
|
||||
return Mono.just(
|
||||
this.keycloak.realm(this.realm).groups().group(groupId).toRepresentation());
|
||||
return Mono.create((Consumer<MonoSink<GroupRepresentation>>) sink ->
|
||||
sink.success(this.keycloak.realm(this.realm)
|
||||
.groups().group(groupId).toRepresentation()))
|
||||
.onErrorMap(NotFoundException.class,
|
||||
ex -> new NoSuchElementException(
|
||||
"Group with id " + groupId + " not exists", ex));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -334,9 +309,13 @@ public class KeycloakAdminReactiveClient {
|
||||
* @return A Mono emitting a list of sub-group representations.
|
||||
*/
|
||||
public Mono<List<GroupRepresentation>> listSubGroups(String parentGroupId) {
|
||||
return Mono.just(this.keycloak.realm(this.realm)
|
||||
return Mono.create((Consumer<MonoSink<List<GroupRepresentation>>>) sink ->
|
||||
sink.success(this.keycloak.realm(this.realm)
|
||||
.groups().group(parentGroupId)
|
||||
.getSubGroups(null, Integer.MAX_VALUE, false));
|
||||
.getSubGroups(null, Integer.MAX_VALUE, false)))
|
||||
.onErrorMap(NotFoundException.class,
|
||||
ex -> new NoSuchElementException(
|
||||
"Group with id " + parentGroupId + " not exists", ex));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -347,10 +326,14 @@ public class KeycloakAdminReactiveClient {
|
||||
* @return A Mono that completes on successful update.
|
||||
*/
|
||||
public Mono<Void> updateGroup(String groupId, GroupRepresentation group) {
|
||||
return Mono.create(sink -> {
|
||||
return Mono
|
||||
.create((Consumer<MonoSink<Void>>) sink -> {
|
||||
this.keycloak.realm(this.realm).groups().group(groupId).update(group);
|
||||
sink.success();
|
||||
});
|
||||
})
|
||||
.onErrorMap(NotFoundException.class, ex -> new NoSuchElementException(
|
||||
"Group with id " + groupId + " not exists"
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -360,10 +343,14 @@ public class KeycloakAdminReactiveClient {
|
||||
* @return A Mono that completes on successful deletion.
|
||||
*/
|
||||
public Mono<Void> deleteGroup(String groupId) {
|
||||
return Mono.create(sink -> {
|
||||
return Mono
|
||||
.create((Consumer<MonoSink<Void>>) sink -> {
|
||||
this.keycloak.realm(this.realm).groups().group(groupId).remove();
|
||||
sink.success();
|
||||
});
|
||||
})
|
||||
.onErrorMap(NotFoundException.class, ex -> new NoSuchElementException(
|
||||
"Group with id " + groupId + " not exists"
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -375,10 +362,14 @@ public class KeycloakAdminReactiveClient {
|
||||
*/
|
||||
public Mono<Void> addMemberToGroup(String groupId, String userId) {
|
||||
// Keycloak API for adding a user to a group is a PUT on the user's groups link
|
||||
return Mono.create(sink -> {
|
||||
return Mono
|
||||
.create((Consumer<MonoSink<Void>>) sink -> {
|
||||
this.keycloak.realm(this.realm).users().get(userId).joinGroup(groupId);
|
||||
sink.success();
|
||||
});
|
||||
})
|
||||
.onErrorMap(ClientErrorException.class, ex -> new IllegalArgumentException(
|
||||
"Failed to add user with id " + userId + " to group with id " + groupId
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -388,8 +379,11 @@ public class KeycloakAdminReactiveClient {
|
||||
* @return A Mono emitting a list of user representations.
|
||||
*/
|
||||
public Mono<List<UserRepresentation>> getGroupMembers(String groupId) {
|
||||
return Mono.just(this.keycloak.realm(this.realm).groups().group(groupId).members());
|
||||
|
||||
return Mono.create((Consumer<MonoSink<List<UserRepresentation>>>) sink -> sink.success(
|
||||
this.keycloak.realm(this.realm).groups().group(groupId).members()))
|
||||
.onErrorMap(NotFoundException.class, ex -> new NoSuchElementException(
|
||||
"Group with id " + groupId + " not exist", ex
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -400,10 +394,14 @@ public class KeycloakAdminReactiveClient {
|
||||
* @return A Mono that completes when the user is removed from the group.
|
||||
*/
|
||||
public Mono<Void> removeMemberFromGroup(String groupId, String userId) {
|
||||
return Mono.create(sink -> {
|
||||
return Mono
|
||||
.create((Consumer<MonoSink<Void>>) sink -> {
|
||||
this.keycloak.realm(this.realm).users().get(userId).leaveGroup(groupId);
|
||||
sink.success();
|
||||
});
|
||||
})
|
||||
.onErrorMap(ClientErrorException.class, ex -> new IllegalArgumentException(
|
||||
"Failed to remove user with id " + userId + " from group with id " + groupId
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -455,8 +453,6 @@ public class KeycloakAdminReactiveClient {
|
||||
"User registration failed due to Keycloak error."
|
||||
+ " Status: " + resp.getStatus()));
|
||||
}
|
||||
} catch (final Throwable t) {
|
||||
sink.error(t);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -468,12 +464,10 @@ public class KeycloakAdminReactiveClient {
|
||||
* @throws NoSuchElementException in mono if keycloak returns 404.
|
||||
*/
|
||||
public Mono<UserRepresentation> getUserDetails(String userId) {
|
||||
try {
|
||||
return Mono.just(this.keycloak.realm(this.realm)
|
||||
.users().get(userId).toRepresentation());
|
||||
} catch (final NotFoundException ex) {
|
||||
return Mono.error(new NoSuchElementException("User with id " + userId + " not exists"));
|
||||
}
|
||||
return Mono.create((Consumer<MonoSink<UserRepresentation>>) sink -> sink.success(
|
||||
this.keycloak.realm(this.realm).users().get(userId).toRepresentation()))
|
||||
.onErrorMap(NotFoundException.class,
|
||||
ex -> new NoSuchElementException("User with id " + userId + " not exists", ex));
|
||||
}
|
||||
|
||||
}
|
||||
+9
-2
@@ -3,10 +3,17 @@ package com.cleverthis.authservice.config;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
@SpringBootTest(properties = {
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@ContextConfiguration(classes = {KeycloakClientConfigPropertiesTest.class})
|
||||
@EnableConfigurationProperties({KeycloakClientConfigProperties.class})
|
||||
@TestPropertySource(properties = {
|
||||
"keycloak.keycloak-host=https://keycloak.example.com",
|
||||
"keycloak.keycloak-admin-host=https://keycloak-admin.example.com",
|
||||
"keycloak.realm=cm-test",
|
||||
|
||||
+238
@@ -0,0 +1,238 @@
|
||||
package com.cleverthis.authservice.controller.rabbitmq;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.ArgumentMatchers.notNull;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.cleverthis.authservice.controller.rabbitmq.exception.EndpointException;
|
||||
import com.cleverthis.authservice.controller.rabbitmq.model.EndpointErrorResponse;
|
||||
import com.cleverthis.authservice.controller.rabbitmq.model.EndpointOkResponse;
|
||||
import com.cleverthis.authservice.controller.rabbitmq.model.EndpointRequest;
|
||||
import com.cleverthis.clevermicro.client.amqp.CleverMicroAmqpClient;
|
||||
import com.cleverthis.clevermicro.client.amqp.handler.HandlerContext;
|
||||
import com.cleverthis.clevermicro.client.amqp.handler.HandlerSubmodule;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.rabbitmq.client.BuiltinExchangeType;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
class AbstractEndpointTest {
|
||||
private final CleverMicroAmqpClient client = Mockito.mock(CleverMicroAmqpClient.class);
|
||||
final ObjectMapper objectMapper = Mockito.spy(new ObjectMapper());
|
||||
|
||||
private class TestEndpoint extends AbstractEndpoint {
|
||||
|
||||
TestEndpoint() throws Exception {
|
||||
super(
|
||||
AbstractEndpointTest.this.client,
|
||||
AbstractEndpointTest.this.objectMapper,
|
||||
"test-key"
|
||||
);
|
||||
}
|
||||
|
||||
// The throws is needed for mocked object to throw exception during test
|
||||
@SuppressWarnings("RedundantThrows")
|
||||
@Override
|
||||
protected void handleRequest(
|
||||
final HandlerContext ctx, final EndpointRequest request
|
||||
) throws EndpointException {
|
||||
}
|
||||
}
|
||||
|
||||
private final HandlerSubmodule handlerSubmodule = Mockito.mock(HandlerSubmodule.class);
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
when(this.client.getHandlerManager()).thenReturn(this.handlerSubmodule);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInitAndClose() throws Exception {
|
||||
when(this.client.getHandlerManager().registerHandler(
|
||||
anyString(), eq(""), eq(1),
|
||||
notNull(), notNull()
|
||||
)).thenReturn("test-tag");
|
||||
final var testEndpoint = new TestEndpoint();
|
||||
verify(this.client.getHandlerManager()).declareExchange(
|
||||
"cleverthis.clevermicro.auth.endpoints", BuiltinExchangeType.DIRECT
|
||||
);
|
||||
verify(this.client.getHandlerManager()).declareQueue(
|
||||
"cleverthis.clevermicro.auth.endpoints.test-key",
|
||||
true, false, false, Map.of()
|
||||
);
|
||||
verify(this.client.getHandlerManager()).bindQueue(
|
||||
"cleverthis.clevermicro.auth.endpoints.test-key",
|
||||
"cleverthis.clevermicro.auth.endpoints",
|
||||
"test-key", Map.of()
|
||||
);
|
||||
|
||||
testEndpoint.close();
|
||||
verify(this.client.getHandlerManager()).cancelHandler("test-tag");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHandler() throws Throwable {
|
||||
final var testEndpoint = Mockito.spy(new TestEndpoint());
|
||||
final var handlerContext = Mockito.mock(HandlerContext.class);
|
||||
|
||||
// silent reply method, it will be tested separately
|
||||
doNothing().when(testEndpoint).reply(eq(handlerContext), notNull());
|
||||
|
||||
// parse req null
|
||||
doReturn(null).when(testEndpoint).parseRequest(notNull());
|
||||
testEndpoint.handleRabbitMessage(handlerContext);
|
||||
verify(testEndpoint).reply(eq(handlerContext), argThat(it -> {
|
||||
final var resp = (EndpointErrorResponse) it;
|
||||
return resp.getException().equals("cleverthis.clevermicro.bad_request")
|
||||
&& resp.getMessage().equals("Malformed request, cannot be parsed");
|
||||
}));
|
||||
|
||||
// path: parse req ok
|
||||
Mockito.clearInvocations(testEndpoint);
|
||||
// handle req ok
|
||||
doReturn(EndpointRequest.builder().build()).when(testEndpoint).parseRequest(notNull());
|
||||
doNothing().when(testEndpoint).handleRequest(notNull(), notNull());
|
||||
assertDoesNotThrow(() -> testEndpoint.handleRabbitMessage(handlerContext));
|
||||
verify(testEndpoint, never()).reply(notNull(), notNull());
|
||||
|
||||
// handle req endpoint exception
|
||||
Mockito.clearInvocations(testEndpoint);
|
||||
doThrow(new EndpointException("test", "message"))
|
||||
.when(testEndpoint).handleRequest(notNull(), notNull());
|
||||
assertDoesNotThrow(() -> testEndpoint.handleRabbitMessage(handlerContext));
|
||||
verify(testEndpoint).reply(notNull(), argThat(it -> {
|
||||
final var resp = (EndpointErrorResponse) it;
|
||||
return resp.getException().equals("test")
|
||||
&& resp.getMessage().equals("message");
|
||||
}));
|
||||
|
||||
// handle req any exception
|
||||
Mockito.clearInvocations(testEndpoint);
|
||||
doThrow(new RuntimeException("test"))
|
||||
.when(testEndpoint).handleRequest(notNull(), notNull());
|
||||
assertDoesNotThrow(() -> testEndpoint.handleRabbitMessage(handlerContext));
|
||||
verify(testEndpoint).reply(notNull(), argThat(it -> {
|
||||
final var resp = (EndpointErrorResponse) it;
|
||||
return resp.getException().equals("cleverthis.clevermicro.server_internal_error");
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseRequest_SingleStream() throws Exception {
|
||||
//noinspection resource
|
||||
final var testEndpoint = new TestEndpoint();
|
||||
final var handlerContext = Mockito.mock(HandlerContext.class);
|
||||
final var inputStream = Mockito.mock(InputStream.class);
|
||||
|
||||
when(handlerContext.getMessageBodySingleStream()).thenReturn(Optional.of(inputStream));
|
||||
final var req = EndpointRequest.builder().method("testMethod").build();
|
||||
doReturn(req).when(this.objectMapper).readValue(inputStream, EndpointRequest.class);
|
||||
|
||||
final var result = testEndpoint.parseRequest(handlerContext);
|
||||
assertEquals(req, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseRequest_MultiStream() throws Exception {
|
||||
//noinspection resource
|
||||
final var testEndpoint = new TestEndpoint();
|
||||
final var handlerContext = Mockito.mock(HandlerContext.class);
|
||||
final var inputStream = Mockito.mock(InputStream.class);
|
||||
|
||||
when(handlerContext.getMessageBodyMultiStream()).thenReturn(Optional.of(
|
||||
Map.of("request", inputStream)
|
||||
));
|
||||
final var req = EndpointRequest.builder().method("testMethod").build();
|
||||
doReturn(req).when(this.objectMapper).readValue(inputStream, EndpointRequest.class);
|
||||
|
||||
final var result = testEndpoint.parseRequest(handlerContext);
|
||||
assertEquals(req, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testReply_SuccessfulSerialization() throws Exception {
|
||||
//noinspection resource
|
||||
final var testEndpoint = new TestEndpoint();
|
||||
final var handlerContext = Mockito.mock(HandlerContext.class);
|
||||
final var response = Map.of("key", "value");
|
||||
|
||||
assertDoesNotThrow(() -> testEndpoint.reply(handlerContext, response));
|
||||
verify(handlerContext).finish("""
|
||||
{
|
||||
"key" : "value"
|
||||
}
|
||||
""".trim().getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testReply_SerializationFailure() throws Exception {
|
||||
//noinspection resource
|
||||
final var testEndpoint = new TestEndpoint();
|
||||
final var handlerContext = Mockito.mock(HandlerContext.class);
|
||||
final var response = mock(EndpointOkResponse.class);
|
||||
// throw error when accessing fields, causing jackson failed to serialize
|
||||
when(response.getResult()).thenThrow(new RuntimeException("test"));
|
||||
|
||||
assertDoesNotThrow(() -> testEndpoint.reply(handlerContext, response));
|
||||
verify(handlerContext, never()).finish(any());
|
||||
verify(handlerContext).refillAvailability();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testReply_ReplyFailure() throws Exception {
|
||||
//noinspection resource
|
||||
final var testEndpoint = new TestEndpoint();
|
||||
final var handlerContext = Mockito.mock(HandlerContext.class);
|
||||
final var response = Map.of("key", "value");
|
||||
|
||||
doThrow(new IOException("Reply error")).when(handlerContext).finish(notNull());
|
||||
|
||||
assertDoesNotThrow(() -> testEndpoint.reply(handlerContext, response));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseRequest_InvalidRequest() throws Exception {
|
||||
//noinspection resource
|
||||
final var testEndpoint = new TestEndpoint();
|
||||
final var handlerContext = Mockito.mock(HandlerContext.class);
|
||||
final var inputStream = Mockito.mock(InputStream.class);
|
||||
|
||||
when(handlerContext.getMessageBodySingleStream()).thenReturn(Optional.of(inputStream));
|
||||
doThrow(new IOException("test")).when(this.objectMapper)
|
||||
.readValue(inputStream, EndpointRequest.class);
|
||||
|
||||
final var result = testEndpoint.parseRequest(handlerContext);
|
||||
assertNull(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testParseRequest_NoStream() throws Exception {
|
||||
//noinspection resource
|
||||
final var testEndpoint = new TestEndpoint();
|
||||
final var handlerContext = Mockito.mock(HandlerContext.class);
|
||||
|
||||
when(handlerContext.getMessageBodySingleStream()).thenReturn(Optional.empty());
|
||||
when(handlerContext.getMessageBodyMultiStream()).thenReturn(Optional.empty());
|
||||
|
||||
final var result = testEndpoint.parseRequest(handlerContext);
|
||||
assertNull(result);
|
||||
}
|
||||
}
|
||||
+955
-6
@@ -1,25 +1,974 @@
|
||||
package com.cleverthis.authservice.service.impl;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.cleverthis.authservice.config.KeycloakClientConfigProperties;
|
||||
import com.cleverthis.authservice.dto.RegistrationRequest;
|
||||
import com.cleverthis.authservice.dto.keycloakadmin.KeycloakInvitationRequest;
|
||||
import com.cleverthis.authservice.exception.RegistrationException;
|
||||
import com.cleverthis.authservice.exception.ServiceUnavailableException;
|
||||
import com.cleverthis.authservice.exception.UserAlreadyExistsException;
|
||||
import jakarta.ws.rs.ClientErrorException;
|
||||
import jakarta.ws.rs.NotFoundException;
|
||||
import jakarta.ws.rs.ProcessingException;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.keycloak.admin.client.Keycloak;
|
||||
import org.keycloak.admin.client.resource.UserResource;
|
||||
import org.keycloak.representations.idm.GroupRepresentation;
|
||||
import org.keycloak.representations.idm.MemberRepresentation;
|
||||
import org.keycloak.representations.idm.OrganizationRepresentation;
|
||||
import org.keycloak.representations.idm.UserRepresentation;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
class KeycloakAdminReactiveClientTest {
|
||||
private KeycloakAdminReactiveClient adminClient;
|
||||
private final Keycloak keycloak = mock(Keycloak.class);
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
final var keycloak = Mockito.mock(Keycloak.class);
|
||||
when(this.keycloak.realm("test-realm")).thenReturn(mock());
|
||||
|
||||
when(this.keycloak.realm("test-realm").organizations()).thenReturn(mock());
|
||||
when(this.keycloak.realm("test-realm").groups()).thenReturn(mock());
|
||||
when(this.keycloak.realm("test-realm").users()).thenReturn(mock());
|
||||
|
||||
final var configProperties = KeycloakClientConfigProperties.builder()
|
||||
.keycloakAdminHost("http://example.com/")
|
||||
.realm("test-realm")
|
||||
.adminAccountUsername("admin")
|
||||
.adminAccountPassword("admin-password")
|
||||
.build();
|
||||
|
||||
this.adminClient = Mockito.spy(new KeycloakAdminReactiveClient(keycloak, configProperties));
|
||||
this.adminClient =
|
||||
Mockito.spy(new KeycloakAdminReactiveClient(this.keycloak, configProperties));
|
||||
}
|
||||
|
||||
// TODO: implement tests
|
||||
@Test
|
||||
void testCreateOrganization_Success() {
|
||||
// Arrange
|
||||
final var orgToCreate = new OrganizationRepresentation();
|
||||
orgToCreate.setId("test-id");
|
||||
orgToCreate.setName("Test Organization");
|
||||
|
||||
final var response = mock(Response.class);
|
||||
when(response.getStatusInfo()).thenReturn(mock());
|
||||
when(response.getStatusInfo().getFamily())
|
||||
.thenReturn(Response.Status.Family.SUCCESSFUL);
|
||||
when(response.readEntity(OrganizationRepresentation.class)).thenReturn(orgToCreate);
|
||||
|
||||
when(this.keycloak.realm("test-realm")
|
||||
.organizations().create(orgToCreate))
|
||||
.thenReturn(response);
|
||||
|
||||
// Act
|
||||
final var result = this.adminClient.createOrganization(orgToCreate).block();
|
||||
|
||||
// Assert
|
||||
assertNotNull(result);
|
||||
assertEquals("Test Organization", result.getName());
|
||||
//noinspection resource
|
||||
verify(this.keycloak.realm("test-realm").organizations()).create(orgToCreate);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateOrganization_Failure() {
|
||||
// Arrange
|
||||
final var orgToCreate = new OrganizationRepresentation();
|
||||
orgToCreate.setId("test-id");
|
||||
orgToCreate.setName("Test Organization");
|
||||
|
||||
final var response = mock(Response.class);
|
||||
when(response.getStatusInfo()).thenReturn(mock());
|
||||
|
||||
// keycloak return non-200
|
||||
when(response.getStatusInfo().getFamily())
|
||||
.thenReturn(Response.Status.Family.CLIENT_ERROR);
|
||||
when(response.readEntity(String.class)).thenReturn("Error occurred");
|
||||
|
||||
when(
|
||||
this.keycloak.realm("test-realm").organizations()
|
||||
.create(orgToCreate))
|
||||
.thenReturn(response);
|
||||
|
||||
// Act & Assert
|
||||
Assertions.assertThrows(ServiceUnavailableException.class,
|
||||
() -> this.adminClient.createOrganization(orgToCreate).block());
|
||||
|
||||
|
||||
// client read exception
|
||||
when(response.getStatusInfo().getFamily())
|
||||
.thenReturn(Response.Status.Family.SUCCESSFUL);
|
||||
when(response.readEntity(OrganizationRepresentation.class))
|
||||
.thenThrow(new ProcessingException("test"));
|
||||
|
||||
when(
|
||||
this.keycloak.realm("test-realm").organizations()
|
||||
.create(orgToCreate))
|
||||
.thenReturn(response);
|
||||
|
||||
// Act & Assert
|
||||
Assertions.assertThrows(ProcessingException.class,
|
||||
() -> this.adminClient.createOrganization(orgToCreate).block());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetOrganizations_Success() {
|
||||
// Arrange
|
||||
final var organization1 = new OrganizationRepresentation();
|
||||
organization1.setId("org-1");
|
||||
organization1.setName("Organization 1");
|
||||
|
||||
final var organization2 = new OrganizationRepresentation();
|
||||
organization2.setId("org-2");
|
||||
organization2.setName("Organization 2");
|
||||
|
||||
when(this.keycloak.realm("test-realm")
|
||||
.organizations().list(null, Integer.MAX_VALUE))
|
||||
.thenReturn(List.of(organization1, organization2));
|
||||
|
||||
// Act
|
||||
final var result = this.adminClient.getOrganizations().block();
|
||||
|
||||
// Assert
|
||||
assertNotNull(result);
|
||||
assertEquals(2, result.size());
|
||||
assertEquals("Organization 1", result.get(0).getName());
|
||||
assertEquals("Organization 2", result.get(1).getName());
|
||||
verify(this.keycloak.realm("test-realm").organizations()).list(null, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetOrganizationById_Success() {
|
||||
// Arrange
|
||||
final var organization = new OrganizationRepresentation();
|
||||
organization.setId("org-1");
|
||||
organization.setName("Test Organization");
|
||||
|
||||
when(this.keycloak.realm("test-realm")
|
||||
.organizations().get("org-1"))
|
||||
.thenReturn(mock());
|
||||
when(this.keycloak.realm("test-realm")
|
||||
.organizations().get("org-1").toRepresentation())
|
||||
.thenReturn(organization);
|
||||
|
||||
// Act
|
||||
final var result = this.adminClient.getOrganizationById("org-1").block();
|
||||
|
||||
// Assert
|
||||
assertNotNull(result);
|
||||
assertEquals("org-1", result.getId());
|
||||
assertEquals("Test Organization", result.getName());
|
||||
verify(this.keycloak.realm("test-realm").organizations().get("org-1"))
|
||||
.toRepresentation();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetOrganizationById_NotFound() {
|
||||
// Arrange
|
||||
when(this.keycloak.realm("test-realm")
|
||||
.organizations().get("non-existing-id"))
|
||||
.thenReturn(mock());
|
||||
when(this.keycloak.realm("test-realm")
|
||||
.organizations().get("non-existing-id").toRepresentation())
|
||||
.thenThrow(new NotFoundException("Organization not found"));
|
||||
|
||||
// Act & Assert
|
||||
Assertions.assertThrows(NoSuchElementException.class,
|
||||
() -> this.adminClient.getOrganizationById("non-existing-id").block());
|
||||
verify(this.keycloak.realm("test-realm").organizations().get("non-existing-id"))
|
||||
.toRepresentation();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUpdateOrganization_Success() {
|
||||
// Arrange
|
||||
final var orgId = "org-1";
|
||||
final var orgToUpdate = new OrganizationRepresentation();
|
||||
orgToUpdate.setId("org-1");
|
||||
orgToUpdate.setName("Updated Organization");
|
||||
|
||||
final var response = mock(Response.class);
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId)).thenReturn(mock());
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId).update(orgToUpdate))
|
||||
.thenReturn(response);
|
||||
when(response.getStatusInfo()).thenReturn(mock());
|
||||
when(response.getStatusInfo().getFamily()).thenReturn(Response.Status.Family.SUCCESSFUL);
|
||||
|
||||
// Act
|
||||
this.adminClient.updateOrganization(orgId, orgToUpdate).block();
|
||||
|
||||
// Assert
|
||||
//noinspection resource
|
||||
verify(this.keycloak.realm("test-realm").organizations().get(orgId)).update(orgToUpdate);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUpdateOrganization_Failure_ClientError() {
|
||||
// Arrange
|
||||
final var orgId = "org-1";
|
||||
final var orgToUpdate = new OrganizationRepresentation();
|
||||
orgToUpdate.setId("org-1");
|
||||
orgToUpdate.setName("Updated Organization");
|
||||
|
||||
final var response = mock(Response.class);
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId)).thenReturn(mock());
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId).update(orgToUpdate))
|
||||
.thenReturn(response);
|
||||
when(response.getStatusInfo()).thenReturn(mock());
|
||||
when(response.getStatusInfo().getFamily()).thenReturn(Response.Status.Family.CLIENT_ERROR);
|
||||
when(response.readEntity(String.class)).thenReturn("Client error occurred");
|
||||
|
||||
// Act & Assert
|
||||
Assertions.assertThrows(ServiceUnavailableException.class,
|
||||
() -> this.adminClient.updateOrganization(orgId, orgToUpdate).block());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUpdateOrganization_Failure_ProcessingException() {
|
||||
// Arrange
|
||||
final var orgId = "org-1";
|
||||
final var orgToUpdate = new OrganizationRepresentation();
|
||||
orgToUpdate.setId("org-1");
|
||||
orgToUpdate.setName("Updated Organization");
|
||||
|
||||
final var response = mock(Response.class);
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId)).thenReturn(mock());
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId).update(orgToUpdate))
|
||||
.thenReturn(response);
|
||||
when(response.getStatusInfo()).thenReturn(mock());
|
||||
when(response.getStatusInfo().getFamily()).thenReturn(Response.Status.Family.SERVER_ERROR);
|
||||
when(response.readEntity(String.class))
|
||||
.thenThrow(new ProcessingException("Processing error"));
|
||||
|
||||
// Act & Assert
|
||||
Assertions.assertThrows(ProcessingException.class,
|
||||
() -> this.adminClient.updateOrganization(orgId, orgToUpdate).block());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDeleteOrganization_Success() {
|
||||
// Arrange
|
||||
final var orgId = "org-1";
|
||||
|
||||
final var response = mock(Response.class);
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId)).thenReturn(mock());
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId).delete())
|
||||
.thenReturn(response);
|
||||
when(response.getStatusInfo()).thenReturn(mock());
|
||||
when(response.getStatusInfo().getFamily()).thenReturn(Response.Status.Family.SUCCESSFUL);
|
||||
|
||||
// Act
|
||||
this.adminClient.deleteOrganization(orgId).block();
|
||||
|
||||
// Assert
|
||||
//noinspection resource
|
||||
verify(this.keycloak.realm("test-realm").organizations().get(orgId)).delete();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDeleteOrganization_Failure_ClientError() {
|
||||
// Arrange
|
||||
final var orgId = "org-1";
|
||||
|
||||
final var response = mock(Response.class);
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId)).thenReturn(mock());
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId).delete())
|
||||
.thenReturn(response);
|
||||
when(response.getStatusInfo()).thenReturn(mock());
|
||||
when(response.getStatusInfo().getFamily()).thenReturn(Response.Status.Family.CLIENT_ERROR);
|
||||
when(response.readEntity(String.class)).thenReturn("Client error occurred");
|
||||
|
||||
// Act & Assert
|
||||
Assertions.assertThrows(ServiceUnavailableException.class,
|
||||
() -> this.adminClient.deleteOrganization(orgId).block());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDeleteOrganization_Failure_ServerError() {
|
||||
// Arrange
|
||||
final var orgId = "org-1";
|
||||
|
||||
final var response = mock(Response.class);
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId)).thenReturn(mock());
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId).delete())
|
||||
.thenReturn(response);
|
||||
when(response.getStatusInfo()).thenReturn(mock());
|
||||
when(response.getStatusInfo().getFamily()).thenReturn(Response.Status.Family.SERVER_ERROR);
|
||||
when(response.readEntity(String.class)).thenReturn("Server error occurred");
|
||||
|
||||
// Act & Assert
|
||||
Assertions.assertThrows(ServiceUnavailableException.class,
|
||||
() -> this.adminClient.deleteOrganization(orgId).block());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInviteUserToOrganization_Success() {
|
||||
// Arrange
|
||||
final var orgId = "org-1";
|
||||
final var invitation = new KeycloakInvitationRequest("test@example.com", "Test", "User");
|
||||
final var response = mock(Response.class);
|
||||
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId)).thenReturn(mock());
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId).members()).thenReturn(
|
||||
mock());
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId).members()
|
||||
.inviteUser(invitation.getEmail(), invitation.getFirstName(),
|
||||
invitation.getLastName()))
|
||||
.thenReturn(response);
|
||||
when(response.getStatusInfo()).thenReturn(mock());
|
||||
when(response.getStatusInfo().getFamily()).thenReturn(Response.Status.Family.SUCCESSFUL);
|
||||
|
||||
// Act
|
||||
this.adminClient.inviteUserToOrganization(orgId, invitation).block();
|
||||
|
||||
// Assert
|
||||
//noinspection resource
|
||||
verify(this.keycloak.realm("test-realm").organizations().get(orgId).members())
|
||||
.inviteUser(invitation.getEmail(), invitation.getFirstName(),
|
||||
invitation.getLastName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInviteUserToOrganization_Failure_ClientError() {
|
||||
// Arrange
|
||||
final var orgId = "org-1";
|
||||
final var invitation = new KeycloakInvitationRequest("test@example.com", "Test", "User");
|
||||
final var response = mock(Response.class);
|
||||
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId)).thenReturn(mock());
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId).members()).thenReturn(
|
||||
mock());
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId).members()
|
||||
.inviteUser(invitation.getEmail(), invitation.getFirstName(),
|
||||
invitation.getLastName()))
|
||||
.thenReturn(response);
|
||||
when(response.getStatusInfo()).thenReturn(mock());
|
||||
when(response.getStatusInfo().getFamily()).thenReturn(Response.Status.Family.CLIENT_ERROR);
|
||||
when(response.readEntity(String.class)).thenReturn("Client error occurred");
|
||||
|
||||
// Act & Assert
|
||||
Assertions.assertThrows(ServiceUnavailableException.class,
|
||||
() -> this.adminClient.inviteUserToOrganization(orgId, invitation).block());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInviteUserToOrganization_Failure_Exception() {
|
||||
// Arrange
|
||||
final var orgId = "org-1";
|
||||
final var invitation = new KeycloakInvitationRequest("test@example.com", "Test", "User");
|
||||
final var response = mock(Response.class);
|
||||
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId)).thenReturn(mock());
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId).members()).thenReturn(
|
||||
mock());
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId).members()
|
||||
.inviteUser(invitation.getEmail(), invitation.getFirstName(),
|
||||
invitation.getLastName()))
|
||||
.thenReturn(response);
|
||||
when(response.getStatusInfo()).thenReturn(mock());
|
||||
when(response.getStatusInfo().getFamily()).thenReturn(Response.Status.Family.SERVER_ERROR);
|
||||
when(response.readEntity(String.class)).thenThrow(new RuntimeException("Unexpected error"));
|
||||
|
||||
// Act & Assert
|
||||
Assertions.assertThrows(RuntimeException.class,
|
||||
() -> this.adminClient.inviteUserToOrganization(orgId, invitation).block());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetOrganizationMembers_Success() {
|
||||
// Arrange
|
||||
final var orgId = "org-1";
|
||||
|
||||
final var member1 = new MemberRepresentation();
|
||||
member1.setId("user-1");
|
||||
member1.setUsername("member1");
|
||||
|
||||
final var member2 = new MemberRepresentation();
|
||||
member2.setId("user-2");
|
||||
member2.setUsername("member2");
|
||||
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId))
|
||||
.thenReturn(mock());
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId).members())
|
||||
.thenReturn(mock());
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId)
|
||||
.members().list(null, Integer.MAX_VALUE))
|
||||
.thenReturn(List.of(member1, member2));
|
||||
|
||||
// Act
|
||||
final var result = this.adminClient.getOrganizationMembers(orgId).block();
|
||||
|
||||
// Assert
|
||||
assertNotNull(result);
|
||||
assertEquals(2, result.size());
|
||||
assertEquals("user-1", result.get(0).getId());
|
||||
assertEquals("user-2", result.get(1).getId());
|
||||
verify(this.keycloak.realm("test-realm").organizations().get(orgId)
|
||||
.members()).list(null, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetOrganizationMembers_Failure_NotFound() {
|
||||
// Arrange
|
||||
final var orgId = "non-existing-org";
|
||||
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId))
|
||||
.thenThrow(new NotFoundException("Organization not found"));
|
||||
|
||||
// Act & Assert
|
||||
Assertions.assertThrows(NoSuchElementException.class,
|
||||
() -> this.adminClient.getOrganizationMembers(orgId).block());
|
||||
verify(this.keycloak.realm("test-realm").organizations()).get(orgId);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAddMemberToOrganization_Success() {
|
||||
// Arrange
|
||||
final var orgId = "org-1";
|
||||
final var userId = "user-1";
|
||||
|
||||
final var response = mock(Response.class);
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId)).thenReturn(mock());
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId).members()).thenReturn(
|
||||
mock());
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId).members()
|
||||
.addMember(userId))
|
||||
.thenReturn(response);
|
||||
when(response.getStatusInfo()).thenReturn(mock());
|
||||
when(response.getStatusInfo().getFamily()).thenReturn(Response.Status.Family.SUCCESSFUL);
|
||||
|
||||
// Act
|
||||
this.adminClient.addMemberToOrganization(orgId, userId).block();
|
||||
|
||||
// Assert
|
||||
//noinspection resource
|
||||
verify(this.keycloak.realm("test-realm").organizations().get(orgId).members())
|
||||
.addMember(userId);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAddMemberToOrganization_Failure_ClientError() {
|
||||
// Arrange
|
||||
final var orgId = "org-1";
|
||||
final var userId = "user-1";
|
||||
|
||||
final var response = mock(Response.class);
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId)).thenReturn(mock());
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId).members()).thenReturn(
|
||||
mock());
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId).members()
|
||||
.addMember(userId))
|
||||
.thenReturn(response);
|
||||
when(response.getStatusInfo()).thenReturn(mock());
|
||||
when(response.getStatusInfo().getFamily()).thenReturn(Response.Status.Family.CLIENT_ERROR);
|
||||
when(response.readEntity(String.class)).thenReturn("Client error occurred");
|
||||
|
||||
// Act & Assert
|
||||
Assertions.assertThrows(ServiceUnavailableException.class,
|
||||
() -> this.adminClient.addMemberToOrganization(orgId, userId).block());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAddMemberToOrganization_Failure_UnexpectedException() {
|
||||
// Arrange
|
||||
final var orgId = "org-1";
|
||||
final var userId = "user-1";
|
||||
|
||||
final var response = mock(Response.class);
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId)).thenReturn(mock());
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId).members()).thenReturn(
|
||||
mock());
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId).members()
|
||||
.addMember(userId))
|
||||
.thenReturn(response);
|
||||
when(response.getStatusInfo()).thenReturn(mock());
|
||||
when(response.getStatusInfo().getFamily()).thenReturn(Response.Status.Family.SERVER_ERROR);
|
||||
when(response.readEntity(String.class)).thenThrow(new RuntimeException("Unexpected error"));
|
||||
|
||||
// Act & Assert
|
||||
Assertions.assertThrows(RuntimeException.class,
|
||||
() -> this.adminClient.addMemberToOrganization(orgId, userId).block());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRemoveMemberFromOrganization_Success() {
|
||||
// Arrange
|
||||
final var orgId = "org-1";
|
||||
final var userId = "user-1";
|
||||
|
||||
final var response = mock(Response.class);
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId)).thenReturn(mock());
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId).members()).thenReturn(
|
||||
mock());
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId).members()
|
||||
.removeMember(userId))
|
||||
.thenReturn(response);
|
||||
when(response.getStatusInfo()).thenReturn(mock());
|
||||
when(response.getStatusInfo().getFamily()).thenReturn(Response.Status.Family.SUCCESSFUL);
|
||||
|
||||
// Act
|
||||
this.adminClient.removeMemberFromOrganization(orgId, userId).block();
|
||||
|
||||
// Assert
|
||||
//noinspection resource
|
||||
verify(this.keycloak.realm("test-realm").organizations().get(orgId).members())
|
||||
.removeMember(userId);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRemoveMemberFromOrganization_Failure_ClientError() {
|
||||
// Arrange
|
||||
final var orgId = "org-1";
|
||||
final var userId = "user-1";
|
||||
|
||||
final var response = mock(Response.class);
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId)).thenReturn(mock());
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId).members()).thenReturn(
|
||||
mock());
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId).members()
|
||||
.removeMember(userId))
|
||||
.thenReturn(response);
|
||||
when(response.getStatusInfo()).thenReturn(mock());
|
||||
when(response.getStatusInfo().getFamily()).thenReturn(Response.Status.Family.CLIENT_ERROR);
|
||||
when(response.readEntity(String.class)).thenReturn("Client error occurred");
|
||||
|
||||
// Act & Assert
|
||||
Assertions.assertThrows(ServiceUnavailableException.class,
|
||||
() -> this.adminClient.removeMemberFromOrganization(orgId, userId).block());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRemoveMemberFromOrganization_Failure_Exception() {
|
||||
// Arrange
|
||||
final var orgId = "org-1";
|
||||
final var userId = "user-1";
|
||||
|
||||
final var response = mock(Response.class);
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId)).thenReturn(mock());
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId).members()).thenReturn(
|
||||
mock());
|
||||
when(this.keycloak.realm("test-realm").organizations().get(orgId).members()
|
||||
.removeMember(userId))
|
||||
.thenReturn(response);
|
||||
when(response.getStatusInfo()).thenReturn(mock());
|
||||
when(response.getStatusInfo().getFamily()).thenReturn(Response.Status.Family.SERVER_ERROR);
|
||||
when(response.readEntity(String.class)).thenThrow(new RuntimeException("Unexpected error"));
|
||||
|
||||
// Act & Assert
|
||||
Assertions.assertThrows(RuntimeException.class,
|
||||
() -> this.adminClient.removeMemberFromOrganization(orgId, userId).block());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateSubGroup_Success() {
|
||||
// Arrange
|
||||
final var parentGroupId = "parent-group-1";
|
||||
final var subGroup = new GroupRepresentation();
|
||||
subGroup.setName("Sub Group 1");
|
||||
|
||||
final var response = mock(Response.class);
|
||||
when(this.keycloak.realm("test-realm").groups().group(parentGroupId)).thenReturn(mock());
|
||||
when(this.keycloak.realm("test-realm").groups().group(parentGroupId).subGroup(subGroup))
|
||||
.thenReturn(response);
|
||||
when(response.getStatusInfo()).thenReturn(mock());
|
||||
when(response.getStatusInfo().getFamily()).thenReturn(Response.Status.Family.SUCCESSFUL);
|
||||
|
||||
// Act
|
||||
this.adminClient.createSubGroup(parentGroupId, subGroup).block();
|
||||
|
||||
// Assert
|
||||
//noinspection resource
|
||||
verify(this.keycloak.realm("test-realm").groups().group(parentGroupId)).subGroup(subGroup);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateSubGroup_Failure_ClientError() {
|
||||
// Arrange
|
||||
final var parentGroupId = "parent-group-1";
|
||||
final var subGroup = new GroupRepresentation();
|
||||
subGroup.setName("Sub Group 1");
|
||||
|
||||
final var response = mock(Response.class);
|
||||
when(this.keycloak.realm("test-realm").groups().group(parentGroupId)).thenReturn(mock());
|
||||
when(this.keycloak.realm("test-realm").groups().group(parentGroupId).subGroup(subGroup))
|
||||
.thenReturn(response);
|
||||
when(response.getStatusInfo()).thenReturn(mock());
|
||||
when(response.getStatusInfo().getFamily()).thenReturn(Response.Status.Family.CLIENT_ERROR);
|
||||
when(response.readEntity(String.class)).thenReturn("Client error occurred");
|
||||
|
||||
// Act & Assert
|
||||
Assertions.assertThrows(ServiceUnavailableException.class,
|
||||
() -> this.adminClient.createSubGroup(parentGroupId, subGroup).block());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreateSubGroup_Failure_Exception() {
|
||||
// Arrange
|
||||
final var parentGroupId = "parent-group-1";
|
||||
final var subGroup = new GroupRepresentation();
|
||||
subGroup.setName("Sub Group 1");
|
||||
|
||||
final var response = mock(Response.class);
|
||||
when(this.keycloak.realm("test-realm").groups().group(parentGroupId)).thenReturn(mock());
|
||||
when(this.keycloak.realm("test-realm").groups().group(parentGroupId).subGroup(subGroup))
|
||||
.thenReturn(response);
|
||||
when(response.getStatusInfo()).thenReturn(mock());
|
||||
when(response.getStatusInfo().getFamily()).thenReturn(Response.Status.Family.SERVER_ERROR);
|
||||
when(response.readEntity(String.class)).thenThrow(new RuntimeException("Unexpected error"));
|
||||
|
||||
// Act & Assert
|
||||
Assertions.assertThrows(RuntimeException.class,
|
||||
() -> this.adminClient.createSubGroup(parentGroupId, subGroup).block());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetGroupById_Success() {
|
||||
// Arrange
|
||||
final var groupId = "group-1";
|
||||
final var group = new GroupRepresentation();
|
||||
group.setId(groupId);
|
||||
group.setName("Test Group");
|
||||
|
||||
when(this.keycloak.realm("test-realm").groups().group(groupId))
|
||||
.thenReturn(mock());
|
||||
when(this.keycloak.realm("test-realm").groups().group(groupId).toRepresentation())
|
||||
.thenReturn(group);
|
||||
|
||||
// Act
|
||||
final var result = this.adminClient.getGroupById(groupId).block();
|
||||
|
||||
// Assert
|
||||
assertNotNull(result);
|
||||
assertEquals("group-1", result.getId());
|
||||
assertEquals("Test Group", result.getName());
|
||||
verify(this.keycloak.realm("test-realm").groups().group(groupId)).toRepresentation();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetGroupById_NotFound() {
|
||||
// Arrange
|
||||
final var groupId = "non-existing-group";
|
||||
|
||||
when(this.keycloak.realm("test-realm").groups().group(groupId))
|
||||
.thenReturn(mock());
|
||||
when(this.keycloak.realm("test-realm").groups().group(groupId).toRepresentation())
|
||||
.thenThrow(new NotFoundException("Group not found"));
|
||||
|
||||
// Act & Assert
|
||||
Assertions.assertThrows(NoSuchElementException.class,
|
||||
() -> this.adminClient.getGroupById(groupId).block());
|
||||
verify(this.keycloak.realm("test-realm").groups().group(groupId)).toRepresentation();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testListSubGroups_Success() {
|
||||
// Arrange
|
||||
final var parentGroupId = "parent-group-1";
|
||||
|
||||
final var subGroup1 = new GroupRepresentation();
|
||||
subGroup1.setId("sub-group-1");
|
||||
subGroup1.setName("Sub Group 1");
|
||||
|
||||
final var subGroup2 = new GroupRepresentation();
|
||||
subGroup2.setId("sub-group-2");
|
||||
subGroup2.setName("Sub Group 2");
|
||||
|
||||
when(this.keycloak.realm("test-realm").groups().group(parentGroupId)).thenReturn(mock());
|
||||
when(this.keycloak.realm("test-realm").groups().group(parentGroupId)
|
||||
.getSubGroups(null, Integer.MAX_VALUE, false))
|
||||
.thenReturn(List.of(subGroup1, subGroup2));
|
||||
|
||||
// Act
|
||||
final var result = this.adminClient.listSubGroups(parentGroupId).block();
|
||||
|
||||
// Assert
|
||||
assertNotNull(result);
|
||||
assertEquals(2, result.size());
|
||||
assertEquals("sub-group-1", result.get(0).getId());
|
||||
assertEquals("sub-group-2", result.get(1).getId());
|
||||
verify(this.keycloak.realm("test-realm").groups().group(parentGroupId))
|
||||
.getSubGroups(null, Integer.MAX_VALUE, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testListSubGroups_NotFound() {
|
||||
// Arrange
|
||||
final var parentGroupId = "non-existing-group";
|
||||
|
||||
when(this.keycloak.realm("test-realm").groups().group(parentGroupId))
|
||||
.thenThrow(new NotFoundException("Group not found"));
|
||||
|
||||
// Act & Assert
|
||||
Assertions.assertThrows(NoSuchElementException.class,
|
||||
() -> this.adminClient.listSubGroups(parentGroupId).block());
|
||||
verify(this.keycloak.realm("test-realm").groups()).group(parentGroupId);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUpdateGroup_Success() {
|
||||
// Arrange
|
||||
final var groupId = "group-1";
|
||||
final var groupToUpdate = new GroupRepresentation();
|
||||
groupToUpdate.setId("group-1");
|
||||
groupToUpdate.setName("Updated Group");
|
||||
|
||||
when(this.keycloak.realm("test-realm").groups().group(groupId)).thenReturn(mock());
|
||||
|
||||
// Act
|
||||
this.adminClient.updateGroup(groupId, groupToUpdate).block();
|
||||
|
||||
// Assert
|
||||
verify(this.keycloak.realm("test-realm").groups().group(groupId)).update(groupToUpdate);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUpdateGroup_NotFound() {
|
||||
// Arrange
|
||||
final var groupId = "non-existing-group";
|
||||
final var groupToUpdate = new GroupRepresentation();
|
||||
groupToUpdate.setId("non-existing-group");
|
||||
groupToUpdate.setName("Non-existing Group");
|
||||
|
||||
when(this.keycloak.realm("test-realm").groups().group(groupId))
|
||||
.thenThrow(new NotFoundException("Group not found"));
|
||||
|
||||
// Act & Assert
|
||||
Assertions.assertThrows(NoSuchElementException.class,
|
||||
() -> this.adminClient.updateGroup(groupId, groupToUpdate).block());
|
||||
verify(this.keycloak.realm("test-realm").groups()).group(groupId);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDeleteGroup_Success() {
|
||||
// Arrange
|
||||
final var groupId = "group-1";
|
||||
when(this.keycloak.realm("test-realm").groups().group(groupId)).thenReturn(mock());
|
||||
|
||||
// Act
|
||||
this.adminClient.deleteGroup(groupId).block();
|
||||
|
||||
// Assert
|
||||
verify(this.keycloak.realm("test-realm").groups().group(groupId)).remove();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDeleteGroup_NotFound() {
|
||||
// Arrange
|
||||
final var groupId = "non-existing-group";
|
||||
when(this.keycloak.realm("test-realm").groups().group(groupId))
|
||||
.thenThrow(new NotFoundException("Group not found"));
|
||||
|
||||
// Act & Assert
|
||||
Assertions.assertThrows(NoSuchElementException.class,
|
||||
() -> this.adminClient.deleteGroup(groupId).block());
|
||||
verify(this.keycloak.realm("test-realm").groups()).group(groupId);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAddMemberToGroup_Success() {
|
||||
// Arrange
|
||||
final var groupId = "group-1";
|
||||
final var userId = "user-1";
|
||||
|
||||
when(this.keycloak.realm("test-realm").users().get(userId)).thenReturn(mock());
|
||||
|
||||
// Act
|
||||
this.adminClient.addMemberToGroup(groupId, userId).block();
|
||||
|
||||
// Assert
|
||||
verify(this.keycloak.realm("test-realm").users().get(userId)).joinGroup(groupId);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAddMemberToGroup_ClientError() {
|
||||
// Arrange
|
||||
final var groupId = "group-1";
|
||||
final var userId = "user-1";
|
||||
|
||||
final var userResource = mock(UserResource.class);
|
||||
when(this.keycloak.realm("test-realm").users().get(userId)).thenReturn(userResource);
|
||||
doThrow(new ClientErrorException(404)).when(userResource).joinGroup(groupId);
|
||||
|
||||
// Act & Assert
|
||||
Assertions.assertThrows(IllegalArgumentException.class,
|
||||
() -> this.adminClient.addMemberToGroup(groupId, userId).block());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetGroupMembers_Success() {
|
||||
// Arrange
|
||||
final var groupId = "group-1";
|
||||
|
||||
final var member1 = new UserRepresentation();
|
||||
member1.setId("user-1");
|
||||
member1.setUsername("member1");
|
||||
|
||||
final var member2 = new UserRepresentation();
|
||||
member2.setId("user-2");
|
||||
member2.setUsername("member2");
|
||||
|
||||
when(this.keycloak.realm("test-realm").groups().group(groupId)).thenReturn(mock());
|
||||
when(this.keycloak.realm("test-realm").groups().group(groupId).members())
|
||||
.thenReturn(List.of(member1, member2));
|
||||
|
||||
// Act
|
||||
final var result = this.adminClient.getGroupMembers(groupId).block();
|
||||
|
||||
// Assert
|
||||
assertNotNull(result);
|
||||
assertEquals(2, result.size());
|
||||
assertEquals("user-1", result.get(0).getId());
|
||||
assertEquals("user-2", result.get(1).getId());
|
||||
verify(this.keycloak.realm("test-realm").groups().group(groupId)).members();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetGroupMembers_GroupNotFound() {
|
||||
// Arrange
|
||||
final var groupId = "non-existing-group";
|
||||
|
||||
when(this.keycloak.realm("test-realm").groups().group(groupId))
|
||||
.thenThrow(new NotFoundException("Group not found"));
|
||||
|
||||
// Act & Assert
|
||||
Assertions.assertThrows(NoSuchElementException.class,
|
||||
() -> this.adminClient.getGroupMembers(groupId).block());
|
||||
verify(this.keycloak.realm("test-realm").groups()).group(groupId);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRemoveMemberFromGroup_Success() {
|
||||
// Arrange
|
||||
final var groupId = "group-1";
|
||||
final var userId = "user-1";
|
||||
|
||||
when(this.keycloak.realm("test-realm").users().get(userId)).thenReturn(mock());
|
||||
|
||||
// Act
|
||||
this.adminClient.removeMemberFromGroup(groupId, userId).block();
|
||||
|
||||
// Assert
|
||||
verify(this.keycloak.realm("test-realm").users().get(userId)).leaveGroup(groupId);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRemoveMemberFromGroup_Failure_ClientError() {
|
||||
// Arrange
|
||||
final var groupId = "group-1";
|
||||
final var userId = "user-1";
|
||||
|
||||
final var userResource = mock(UserResource.class);
|
||||
when(this.keycloak.realm("test-realm").users().get(userId)).thenReturn(userResource);
|
||||
doThrow(new ClientErrorException(404)).when(userResource).leaveGroup(groupId);
|
||||
|
||||
// Act & Assert
|
||||
Assertions.assertThrows(IllegalArgumentException.class,
|
||||
() -> this.adminClient.removeMemberFromGroup(groupId, userId).block());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRegisterUser_Success() {
|
||||
// Arrange
|
||||
final var registrationRequest = new RegistrationRequest(
|
||||
"John", "Doe", "john@example.com", "password123"
|
||||
);
|
||||
|
||||
final var response = mock(Response.class);
|
||||
when(this.keycloak.realm("test-realm").users().create(any(UserRepresentation.class)))
|
||||
.thenReturn(response);
|
||||
when(response.getStatusInfo()).thenReturn(mock());
|
||||
when(response.getStatusInfo().getFamily()).thenReturn(Response.Status.Family.SUCCESSFUL);
|
||||
|
||||
// Act
|
||||
this.adminClient.registerUser(registrationRequest).block();
|
||||
|
||||
// Assert
|
||||
//noinspection resource
|
||||
verify(this.keycloak.realm("test-realm").users())
|
||||
.create(argThat(user -> user.getUsername().equals("john@example.com")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRegisterUser_UserAlreadyExists() {
|
||||
// Arrange
|
||||
final var registrationRequest = new RegistrationRequest(
|
||||
"John", "Doe", "john@example.com", "password123"
|
||||
);
|
||||
|
||||
final var response = mock(Response.class);
|
||||
when(this.keycloak.realm("test-realm").users().create(any(UserRepresentation.class)))
|
||||
.thenReturn(response);
|
||||
when(response.getStatusInfo()).thenReturn(mock());
|
||||
when(response.getStatusInfo().getFamily()).thenReturn(Response.Status.Family.CLIENT_ERROR);
|
||||
when(response.getStatus()).thenReturn(409);
|
||||
|
||||
// Act & Assert
|
||||
Assertions.assertThrows(UserAlreadyExistsException.class,
|
||||
() -> this.adminClient.registerUser(registrationRequest).block());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRegisterUser_ServerError() {
|
||||
// Arrange
|
||||
final var registrationRequest = new RegistrationRequest(
|
||||
"John", "Doe", "john@example.com", "password123"
|
||||
);
|
||||
|
||||
final var response = mock(Response.class);
|
||||
when(this.keycloak.realm("test-realm").users().create(any(UserRepresentation.class)))
|
||||
.thenReturn(response);
|
||||
when(response.getStatusInfo()).thenReturn(mock());
|
||||
when(response.getStatusInfo().getFamily()).thenReturn(Response.Status.Family.SERVER_ERROR);
|
||||
when(response.readEntity(String.class)).thenReturn("Internal Server Error");
|
||||
|
||||
// Act & Assert
|
||||
Assertions.assertThrows(RegistrationException.class,
|
||||
() -> this.adminClient.registerUser(registrationRequest).block());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetUserDetails_Success() {
|
||||
// Arrange
|
||||
final var userId = "user-1";
|
||||
final var userRepresentation = new UserRepresentation();
|
||||
userRepresentation.setId(userId);
|
||||
userRepresentation.setUsername("user1");
|
||||
|
||||
when(this.keycloak.realm("test-realm").users().get(userId)).thenReturn(mock());
|
||||
when(this.keycloak.realm("test-realm").users().get(userId).toRepresentation())
|
||||
.thenReturn(userRepresentation);
|
||||
|
||||
// Act
|
||||
final var result = this.adminClient.getUserDetails(userId).block();
|
||||
|
||||
// Assert
|
||||
assertNotNull(result);
|
||||
assertEquals("user-1", result.getId());
|
||||
assertEquals("user1", result.getUsername());
|
||||
verify(this.keycloak.realm("test-realm").users().get(userId)).toRepresentation();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetUserDetails_UserNotFound() {
|
||||
// Arrange
|
||||
final var userId = "non-existing-user";
|
||||
|
||||
when(this.keycloak.realm("test-realm").users().get(userId)).thenReturn(mock());
|
||||
when(this.keycloak.realm("test-realm").users().get(userId).toRepresentation())
|
||||
.thenThrow(new NotFoundException("User not found"));
|
||||
|
||||
// Act & Assert
|
||||
Assertions.assertThrows(NoSuchElementException.class,
|
||||
() -> this.adminClient.getUserDetails(userId).block());
|
||||
verify(this.keycloak.realm("test-realm").users().get(userId)).toRepresentation();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user